Build Logs
gmethvin/directory-watcher • scheduled_3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY
Errors
94
Warnings
2600
Total Lines
2920
1##################################
2Clonning https://github.com/gmethvin/directory-watcher.git into repo using revision v0.18.0
3##################################
4Note: switching to '32693b3e0e99c20f84b65e071f9ba7fdeba579b6'.
5
6You are in 'detached HEAD' state. You can look around, make experimental
7changes and commit them, and you can discard any commits you make in this
8state without impacting any branches by switching back to a branch.
9
10If you want to create a new branch to retain commits you create, you may
11do so (now or later) by using -c with the switch command. Example:
12
13 git switch -c <new-branch-name>
14
15Or undo this operation with:
16
17 git switch -
18
19Turn off this advice by setting config variable advice.detachedHead to false
20
21----
22Preparing build for 3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY
23Scala binary version found: 3.7
24Implicitly using source version 3.7-migration
25Scala binary version found: 3.7
26Implicitly using source version 3.7-migration
27Would try to apply common scalacOption (best-effort, sbt/mill only):
28Append: ,-source:3.7-migration,-Wconf:msg=can be rewritten automatically under:s
29Remove: ,-deprecation,-feature,-Xfatal-warnings,-Werror,MATCH:.*-Wconf.*any:e,-migration,
30----
31Starting build for 3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY
32Execute tests: false
33sbt project found:
34No prepare script found for project gmethvin/directory-watcher
35##################################
36Scala version: 3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY
37Targets: io.methvin%directory-watcher-better-files
38Project projectConfig: { "projects": { "exclude": [], "overrides": {} }, "java": { "version": "17" }, "sbt": { "commands": [], "options": [] }, "mill": { "options": [] }, "tests": "compile-only", "migrationVersions": [], "sourcePatches": [] }
39##################################
40Using extra scalacOptions: ,-source:3.7-migration,-Wconf:msg=can be rewritten automatically under:s
41Filtering out scalacOptions: ,-deprecation,-feature,-Xfatal-warnings,-Werror,MATCH:.*-Wconf.*any:e,-migration,
42[sbt_options] declare -a sbt_options=()
43[process_args] java_version = '17'
44[copyRt] java9_rt = '/root/.sbt/1.0/java9-rt-ext-eclipse_adoptium_17_0_8/rt.jar'
45# Executing command line:
46java
47-Xms512M
48-Xmx4096M
49-Xss2M
50-XX:MaxMetaspaceSize=1024M
51-Dcommunitybuild.scala=3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY
52-Dcommunitybuild.project.dependencies.add=
53-Xmx7G
54-Xms4G
55-Xss8M
56-Dsbt.script=/root/.sdkman/candidates/sbt/current/bin/sbt
57-Dscala.ext.dirs=/root/.sbt/1.0/java9-rt-ext-eclipse_adoptium_17_0_8
58-jar
59/root/.sdkman/candidates/sbt/1.9.6/bin/sbt-launch.jar
60"setCrossScalaVersions 3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY"
61"++3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY -v"
62"mapScalacOptions ",-source:3.7-migration,-Wconf:msg=can be rewritten automatically under:s" ",-deprecation,-feature,-Xfatal-warnings,-Werror,MATCH:.*-Wconf.*any:e,-migration,""
63"set every credentials := Nil"
64"excludeLibraryDependency com.github.ghik:zerowaste_{scalaVersion} com.olegpy:better-monadic-for_3 org.polyvariant:better-tostring_{scalaVersion} org.wartremover:wartremover_{scalaVersion}"
65"removeScalacOptionsStartingWith -P:wartremover"
66
67moduleMappings
68"runBuild 3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY """{
69 "projects": {
70 "exclude": [],
71 "overrides": {}
72 },
73 "java": {
74 "version": "17"
75 },
76 "sbt": {
77 "commands": [],
78 "options": []
79 },
80 "mill": {
81 "options": []
82 },
83 "tests": "compile-only",
84 "migrationVersions": [],
85 "sourcePatches": []
86}""" io.methvin%directory-watcher-better-files"
87
88[info] [launcher] getting org.scala-sbt sbt 1.7.1 (this may take some time)...
89[info] [launcher] getting Scala 2.12.16 (for sbt)...
90[info] welcome to sbt 1.7.1 (Eclipse Adoptium Java 17.0.8)
91[info] loading settings for project repo-build from plugins.sbt ...
92[info] loading project definition from /build/repo/project
93[info] compiling 2 Scala sources to /build/repo/project/target/scala-2.12/sbt-1.0/classes ...
94[info] Non-compiled module 'compiler-bridge_2.12' for Scala 2.12.16. Compiling...
95[info] Compilation completed in 8.772s.
96[info] done compiling
97[info] loading settings for project root from build.sbt,version.sbt ...
98[info] set current project to root (in build file:/build/repo/)
99Execute setCrossScalaVersions: 3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY
100OpenCB::Changing crossVersion 3.2.2 -> 3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY in directory-watcher/crossScalaVersions
101OpenCB::Changing crossVersion 3.2.2 -> 3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY in root/crossScalaVersions
102OpenCB::Changing crossVersion 3.2.2 -> 3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY in directory-watcher-better-files/crossScalaVersions
103[info] set current project to root (in build file:/build/repo/)
104[info] Setting Scala version to 3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY on 3 projects.
105[info] Switching Scala version on:
106[info] * root (3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY)
107[info] directory-watcher (3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY)
108[info] directory-watcher-better-files (3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY, 2.13.10, 2.12.10)
109[info] Excluding projects:
110[info] Reapplying settings...
111[info] set current project to root (in build file:/build/repo/)
112Execute mapScalacOptions: ,-source:3.7-migration,-Wconf:msg=can be rewritten automatically under:s ,-deprecation,-feature,-Xfatal-warnings,-Werror,MATCH:.*-Wconf.*any:e,-migration,
113[info] Reapplying settings...
114[info] set current project to root (in build file:/build/repo/)
115[info] Defining Global / credentials, credentials and 1 others.
116[info] The new values will be used by Global / pgpSelectPassphrase, Global / pgpSigningKey and 14 others.
117[info] Run `last` for details.
118[info] Reapplying settings...
119[info] set current project to root (in build file:/build/repo/)
120Execute excludeLibraryDependency: com.github.ghik:zerowaste_{scalaVersion} com.olegpy:better-monadic-for_3 org.polyvariant:better-tostring_{scalaVersion} org.wartremover:wartremover_{scalaVersion}
121[info] Reapplying settings...
122OpenCB::Failed to reapply settings in excludeLibraryDependency: Reference to undefined setting:
123
124 Global / allExcludeDependencies from Global / allExcludeDependencies (CommunityBuildPlugin.scala:315)
125 Did you mean allExcludeDependencies ?
126 , retry without global scopes
127[info] Reapplying settings...
128[info] set current project to root (in build file:/build/repo/)
129Execute removeScalacOptionsStartingWith: -P:wartremover
130[info] Reapplying settings...
131[info] set current project to root (in build file:/build/repo/)
132[success] Total time: 0 s, completed Apr 4, 2025, 11:20:49 AM
133Build config: {
134 "projects": {
135 "exclude": [],
136 "overrides": {}
137 },
138 "java": {
139 "version": "17"
140 },
141 "sbt": {
142 "commands": [],
143 "options": []
144 },
145 "mill": {
146 "options": []
147 },
148 "tests": "compile-only",
149 "migrationVersions": [],
150 "sourcePatches": []
151}
152Parsed config: Success(ProjectBuildConfig(ProjectsConfig(List(),Map()),CompileOnly,List()))
153Starting build...
154Projects: Set(directory-watcher-better-files, directory-watcher)
155Starting build for ProjectRef(file:/build/repo/,directory-watcher-better-files) (directory-watcher-better-files)...
156OpenCB::Exclude Scala3 specific scalacOption `-source:3.7-migration` in Scala 2.12.16 module Global
157OpenCB::Would not apply setting `-source:3.7-migration`: Project has predefined source version: Some(-source:3.7-migration)
158Compile scalacOptions: List(-target:jvm-1.8, -source:3.7-migration, -Wconf:msg=can be rewritten automatically under:s)
159[info] scalafmt: Formatting 1 Scala sources (/build/repo/better-files)...
160[info] compiling 28 Java sources to /build/repo/core/target/classes ...
161[info] scalafmt: Formatting 1 Scala sources (/build/repo/better-files)...
162[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:20:1: <T>loadLibrary(java.lang.String,java.lang.Class<T>) in com.sun.jna.Native has been deprecated
163[warn] Native.loadLibrary
164[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:20:1: redundant cast to io.methvin.watchservice.jna.CarbonAPI
165[warn] (CarbonAPI) Native.loadLibrary("Carbon", CarbonAPI.class)
166[info] done compiling
167[info] compiling 1 Scala source to /build/repo/better-files/target/scala-3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY/classes ...
168[warn] bad option '-target:jvm-1.8' was ignored
169[warn] one warning found
170[info] done compiling
171[info] Main Scala API documentation to /build/repo/better-files/target/scala-3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY/api...
172[warn] bad option '-target:jvm-1.8' was ignored
173[info] Skipping unused scalacOptions: -Wconf, -source
174[warn] Flag -classpath set repeatedly
175[warn] two warnings found
176[info] Main Scala API documentation successful.
177[info] compiling 1 Scala source to /build/repo/better-files/target/scala-3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY/test-classes ...
178[warn] bad option '-target:jvm-1.8' was ignored
179[warn] one warning found
180[info] done compiling
181[info] Wrote /build/repo/better-files/target/scala-3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY/directory-watcher-better-files_3-0.18.0.pom
182[info] Main Scala API documentation to /build/repo/better-files/target/scala-3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY/api...
183[warn] bad option '-target:jvm-1.8' was ignored
184[info] Skipping unused scalacOptions: -Wconf, -source
185[warn] Flag -classpath set repeatedly
186[warn] two warnings found
187[info] Main Scala API documentation successful.
188[info] :: delivering :: io.methvin#directory-watcher-better-files_3;0.18.0 :: 0.18.0 :: release :: Fri Apr 04 11:21:08 CEST 2025
189[info] delivering ivy file to /build/repo/better-files/target/scala-3.7.1-RC1-bin-20250402-a8cf11d-NIGHTLY/ivy-0.18.0.xml
190[info] published directory-watcher-better-files_3 to /root/.ivy2/local/io.methvin/directory-watcher-better-files_3/0.18.0/poms/directory-watcher-better-files_3.pom
191[info] published directory-watcher-better-files_3 to /root/.ivy2/local/io.methvin/directory-watcher-better-files_3/0.18.0/jars/directory-watcher-better-files_3.jar
192[info] published directory-watcher-better-files_3 to /root/.ivy2/local/io.methvin/directory-watcher-better-files_3/0.18.0/srcs/directory-watcher-better-files_3-sources.jar
193[info] published directory-watcher-better-files_3 to /root/.ivy2/local/io.methvin/directory-watcher-better-files_3/0.18.0/docs/directory-watcher-better-files_3-javadoc.jar
194[info] published ivy to /root/.ivy2/local/io.methvin/directory-watcher-better-files_3/0.18.0/ivys/ivy.xml
195Starting build for ProjectRef(file:/build/repo/,directory-watcher) (directory-watcher)...
196Compile scalacOptions: List(-target:jvm-1.8, -source:3.7-migration, -Wconf:msg=can be rewritten automatically under:s)
197[info] Main Java API documentation to /build/repo/core/target/api...
198[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:18:1: no comment
199[warn] public interface CarbonAPI extends Library {
200[warn] // sbt uses JNA 4.5.0, so use JNA 4.x's API
201[warn] CarbonAPI INSTANCE = (CarbonAPI) Native.loadLibrary("Carbon", CarbonAPI.class);
202[warn]
203[warn] CFArrayRef CFArrayCreate(
204[warn] CFAllocatorRef allocator, // always set to Pointer.NULL
205[warn] Pointer[] values,
206[warn] CFIndex numValues,
207[warn] Void callBacks // always set to Pointer.NULL
208[warn] );
209[warn]
210[warn] CFStringRef CFStringCreateWithCharacters(
211[warn] Void alloc, // always pass NULL
212[warn] char[] chars,
213[warn] CFIndex numChars);
214[warn]
215[warn] public FSEventStreamRef FSEventStreamCreate(
216[warn] Pointer v, // always use Pointer.NULL
217[warn] FSEventStreamCallback callback,
218[warn] Pointer context, // always use Pointer.NULL
219[warn] CFArrayRef pathsToWatch,
220[warn] long sinceWhen, // use -1 for events since now
221[warn] double latency, // in seconds
222[warn] int flags // 0 is good for now
223[warn] );
224[warn]
225[warn] boolean FSEventStreamStart(FSEventStreamRef streamRef);
226[warn]
227[warn] void FSEventStreamStop(FSEventStreamRef streamRef);
228[warn]
229[warn] void FSEventStreamScheduleWithRunLoop(
230[warn] FSEventStreamRef streamRef, CFRunLoopRef runLoop, CFStringRef runLoopMode);
231[warn]
232[warn] void FSEventStreamUnscheduleFromRunLoop(
233[warn] FSEventStreamRef streamRef, CFRunLoopRef runLoop, CFStringRef runLoopMode);
234[warn]
235[warn] void FSEventStreamInvalidate(FSEventStreamRef streamRef);
236[warn]
237[warn] void FSEventStreamRelease(FSEventStreamRef streamRef);
238[warn]
239[warn] CFRunLoopRef CFRunLoopGetCurrent();
240[warn]
241[warn] void CFRunLoopRun();
242[warn]
243[warn] void CFRunLoopStop(CFRunLoopRef runLoopRef);
244[warn]
245[warn] public interface FSEventStreamCallback extends Callback {
246[warn] @SuppressWarnings({"UnusedDeclaration"})
247[warn] void invoke(
248[warn] FSEventStreamRef streamRef,
249[warn] Pointer clientCallBackInfo,
250[warn] NativeLong numEvents,
251[warn] Pointer eventPaths,
252[warn] Pointer eventFlags,
253[warn] Pointer eventIds);
254[warn] }
255[warn] }
256[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:64:1: no comment
257[warn] public interface FSEventStreamCallback extends Callback {
258[warn] @SuppressWarnings({"UnusedDeclaration"})
259[warn] void invoke(
260[warn] FSEventStreamRef streamRef,
261[warn] Pointer clientCallBackInfo,
262[warn] NativeLong numEvents,
263[warn] Pointer eventPaths,
264[warn] Pointer eventFlags,
265[warn] Pointer eventIds);
266[warn] }
267[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:20:1: no comment
268[warn] CarbonAPI INSTANCE = (CarbonAPI) Native.loadLibrary("Carbon", CarbonAPI.class);
269[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:22:1: no comment
270[warn] CFArrayRef CFArrayCreate(
271[warn] CFAllocatorRef allocator, // always set to Pointer.NULL
272[warn] Pointer[] values,
273[warn] CFIndex numValues,
274[warn] Void callBacks // always set to Pointer.NULL
275[warn] );
276[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:58:1: no comment
277[warn] CFRunLoopRef CFRunLoopGetCurrent();
278[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:60:1: no comment
279[warn] void CFRunLoopRun();
280[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:62:1: no comment
281[warn] void CFRunLoopStop(CFRunLoopRef runLoopRef);
282[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:29:1: no comment
283[warn] CFStringRef CFStringCreateWithCharacters(
284[warn] Void alloc, // always pass NULL
285[warn] char[] chars,
286[warn] CFIndex numChars);
287[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:34:1: no comment
288[warn] public FSEventStreamRef FSEventStreamCreate(
289[warn] Pointer v, // always use Pointer.NULL
290[warn] FSEventStreamCallback callback,
291[warn] Pointer context, // always use Pointer.NULL
292[warn] CFArrayRef pathsToWatch,
293[warn] long sinceWhen, // use -1 for events since now
294[warn] double latency, // in seconds
295[warn] int flags // 0 is good for now
296[warn] );
297[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:54:1: no comment
298[warn] void FSEventStreamInvalidate(FSEventStreamRef streamRef);
299[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:56:1: no comment
300[warn] void FSEventStreamRelease(FSEventStreamRef streamRef);
301[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:48:1: no comment
302[warn] void FSEventStreamScheduleWithRunLoop(
303[warn] FSEventStreamRef streamRef, CFRunLoopRef runLoop, CFStringRef runLoopMode);
304[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:44:1: no comment
305[warn] boolean FSEventStreamStart(FSEventStreamRef streamRef);
306[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:46:1: no comment
307[warn] void FSEventStreamStop(FSEventStreamRef streamRef);
308[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:51:1: no comment
309[warn] void FSEventStreamUnscheduleFromRunLoop(
310[warn] FSEventStreamRef streamRef, CFRunLoopRef runLoop, CFStringRef runLoopMode);
311[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:66:1: no comment
312[warn] @SuppressWarnings({"UnusedDeclaration"})
313[warn] void invoke(
314[warn] FSEventStreamRef streamRef,
315[warn] Pointer clientCallBackInfo,
316[warn] NativeLong numEvents,
317[warn] Pointer eventPaths,
318[warn] Pointer eventFlags,
319[warn] Pointer eventIds);
320[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CFAllocatorRef.java:18:1: no comment
321[warn] public class CFAllocatorRef extends PointerByReference {}
322[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CFArrayRef.java:18:1: no comment
323[warn] public class CFArrayRef extends PointerByReference {}
324[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CFIndex.java:18:1: no comment
325[warn] public class CFIndex extends NativeLong {
326[warn] private static final long serialVersionUID = 0;
327[warn]
328[warn] public static CFIndex valueOf(int i) {
329[warn] CFIndex idx = new CFIndex();
330[warn] idx.setValue(i);
331[warn] return idx;
332[warn] }
333[warn] }
334[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CFIndex.java:21:1: no comment
335[warn] public static CFIndex valueOf(int i) {
336[warn] CFIndex idx = new CFIndex();
337[warn] idx.setValue(i);
338[warn] return idx;
339[warn] }
340[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CFRunLoopRef.java:18:1: no comment
341[warn] public class CFRunLoopRef extends PointerByReference {}
342[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CFStringRef.java:18:1: no comment
343[warn] public class CFStringRef extends PointerByReference {
344[warn]
345[warn] public static CFStringRef toCFString(String s) {
346[warn] final char[] chars = s.toCharArray();
347[warn] int length = chars.length;
348[warn] return CarbonAPI.INSTANCE.CFStringCreateWithCharacters(null, chars, CFIndex.valueOf(length));
349[warn] }
350[warn] }
351[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CFStringRef.java:20:1: no comment
352[warn] public static CFStringRef toCFString(String s) {
353[warn] final char[] chars = s.toCharArray();
354[warn] int length = chars.length;
355[warn] return CarbonAPI.INSTANCE.CFStringCreateWithCharacters(null, chars, CFIndex.valueOf(length));
356[warn] }
357[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSet.java:5:1: no comment
358[warn] public interface ChangeSet {
359[warn] Set<ChangeSetEntry> created();
360[warn]
361[warn] Set<ChangeSetEntry> modified();
362[warn]
363[warn] Set<ChangeSetEntry> deleted();
364[warn] }
365[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSet.java:6:1: no comment
366[warn] Set<ChangeSetEntry> created();
367[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSet.java:10:1: no comment
368[warn] Set<ChangeSetEntry> deleted();
369[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSet.java:8:1: no comment
370[warn] Set<ChangeSetEntry> modified();
371[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSetEntry.java:7:1: no comment
372[warn] public final class ChangeSetEntry {
373[warn]
374[warn] private final Path path;
375[warn] private final boolean isDirectory;
376[warn] private final FileHash hash;
377[warn] private final Path rootPath;
378[warn]
379[warn] ChangeSetEntry(Path path, boolean isDirectory, FileHash hash, Path rootPath) {
380[warn] this.path = path;
381[warn] this.isDirectory = isDirectory;
382[warn] this.hash = hash;
383[warn] this.rootPath = rootPath;
384[warn] }
385[warn]
386[warn] public Path path() {
387[warn] return path;
388[warn] }
389[warn]
390[warn] public boolean isDirectory() {
391[warn] return isDirectory;
392[warn] }
393[warn]
394[warn] public FileHash hash() {
395[warn] return hash;
396[warn] }
397[warn]
398[warn] public Path rootPath() {
399[warn] return rootPath;
400[warn] }
401[warn]
402[warn] @Override
403[warn] public boolean equals(Object o) {
404[warn] if (this == o) {
405[warn] return true;
406[warn] }
407[warn] if (o == null || getClass() != o.getClass()) {
408[warn] return false;
409[warn] }
410[warn]
411[warn] ChangeSetEntry that = (ChangeSetEntry) o;
412[warn]
413[warn] return isDirectory == that.isDirectory
414[warn] && path.equals(that.path)
415[warn] && hash.equals(that.hash)
416[warn] && rootPath.equals(that.rootPath);
417[warn] }
418[warn]
419[warn] @Override
420[warn] public int hashCode() {
421[warn] return Objects.hash(path, isDirectory, rootPath, hash);
422[warn] }
423[warn] }
424[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSetEntry.java:29:1: no comment
425[warn] public FileHash hash() {
426[warn] return hash;
427[warn] }
428[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSetEntry.java:25:1: no comment
429[warn] public boolean isDirectory() {
430[warn] return isDirectory;
431[warn] }
432[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSetEntry.java:21:1: no comment
433[warn] public Path path() {
434[warn] return path;
435[warn] }
436[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSetEntry.java:33:1: no comment
437[warn] public Path rootPath() {
438[warn] return rootPath;
439[warn] }
440[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeListener.java:61:1: no @return
441[warn] default boolean isWatching() {
442[warn] return true;
443[warn] }
444[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeListener.java:72:1: no @param for e
445[warn] default void onException(Exception e) {
446[warn] // Ignore exceptions by default (they will be logged by the watcher)
447[warn] }
448[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSetListener.java:10:1: no comment
449[warn] public final class ChangeSetListener implements DirectoryChangeListener {
450[warn]
451[warn] private Map<Path, ChangeSetBuilder> changeBuilders = new HashMap<>();
452[warn]
453[warn] private final Object lock = new Object() {};
454[warn]
455[warn] @Override
456[warn] public void onEvent(DirectoryChangeEvent event) {
457[warn] Path rootPath = event.rootPath();
458[warn] Path path = event.path();
459[warn]
460[warn] synchronized (lock) {
461[warn] // Maintain a ChangeSet per rootPath
462[warn] ChangeSetBuilder builder = changeBuilders.get(rootPath);
463[warn] if (builder == null) {
464[warn] builder = new ChangeSetBuilder();
465[warn] changeBuilders.put(rootPath, builder);
466[warn] }
467[warn]
468[warn] ChangeSetEntry entry =
469[warn] new ChangeSetEntry(path, event.isDirectory(), event.hash(), event.rootPath());
470[warn]
471[warn] switch (event.eventType()) {
472[warn] case CREATE:
473[warn] builder.addCreated(entry);
474[warn] break;
475[warn] case MODIFY:
476[warn] builder.addModified(entry);
477[warn] break;
478[warn] case DELETE:
479[warn] builder.addDeleted(entry);
480[warn] break;
481[warn] case OVERFLOW:
482[warn] throw new IllegalStateException("OVERFLOW not yet handled");
483[warn] }
484[warn] }
485[warn] }
486[warn]
487[warn] public Map<Path, ChangeSet> getChangeSet() {
488[warn] Map<Path, ChangeSetBuilder> returnBuilders;
489[warn] synchronized (lock) {
490[warn] returnBuilders = changeBuilders;
491[warn] changeBuilders = new HashMap<>();
492[warn] }
493[warn] return returnBuilders.entrySet().stream()
494[warn] .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().toChangeSet()));
495[warn] }
496[warn] }
497[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSetListener.java:48:1: no comment
498[warn] public Map<Path, ChangeSet> getChangeSet() {
499[warn] Map<Path, ChangeSetBuilder> returnBuilders;
500[warn] synchronized (lock) {
501[warn] returnBuilders = changeBuilders;
502[warn] changeBuilders = new HashMap<>();
503[warn] }
504[warn] return returnBuilders.entrySet().stream()
505[warn] .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().toChangeSet()));
506[warn] }
507[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeListener.java:58:1: no comment
508[warn] void onEvent(DirectoryChangeEvent event) throws IOException;
509[warn] /build/repo/core/src/main/java/io/methvin/watcher/visitor/DefaultFileTreeVisitor.java:10:1: no comment
510[warn] public class DefaultFileTreeVisitor implements FileTreeVisitor {
511[warn] @Override
512[warn] public void recursiveVisitFiles(Path file, Callback onDirectory, Callback onFile)
513[warn] throws IOException {
514[warn] SimpleFileVisitor<Path> visitor =
515[warn] new SimpleFileVisitor<Path>() {
516[warn] @Override
517[warn] public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
518[warn] throws IOException {
519[warn] onDirectory.call(dir);
520[warn] return FileVisitResult.CONTINUE;
521[warn] }
522[warn]
523[warn] @Override
524[warn] public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
525[warn] throws IOException {
526[warn] onFile.call(file);
527[warn] return FileVisitResult.CONTINUE;
528[warn] }
529[warn]
530[warn] @Override
531[warn] public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
532[warn] onFailure(file, exc);
533[warn] return FileVisitResult.CONTINUE;
534[warn] }
535[warn]
536[warn] @Override
537[warn] public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
538[warn] if (exc != null) onFailure(dir, exc);
539[warn] return FileVisitResult.CONTINUE;
540[warn] }
541[warn] };
542[warn] Files.walkFileTree(file, visitor);
543[warn] }
544[warn]
545[warn] // To be overridden if needed
546[warn] protected void onFailure(Path path, IOException exception) throws IOException {}
547[warn] }
548[warn] /build/repo/core/src/main/java/io/methvin/watcher/visitor/DefaultFileTreeVisitor.java:46:1: no comment
549[warn] protected void onFailure(Path path, IOException exception) throws IOException {}
550[warn] /build/repo/core/src/main/java/io/methvin/watcher/visitor/FileTreeVisitor.java:16:1: no comment
551[warn] void recursiveVisitFiles(Path file, Callback onDirectory, Callback onFile) throws IOException;
552[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:22:1: no comment
553[warn] public final class DirectoryChangeEvent {
554[warn] public enum EventType {
555[warn]
556[warn] /* A new file was created */
557[warn] CREATE(StandardWatchEventKinds.ENTRY_CREATE),
558[warn]
559[warn] /* An existing file was modified */
560[warn] MODIFY(StandardWatchEventKinds.ENTRY_MODIFY),
561[warn]
562[warn] /* A file was deleted */
563[warn] DELETE(StandardWatchEventKinds.ENTRY_DELETE),
564[warn]
565[warn] /* An overflow occurred; some events were lost */
566[warn] OVERFLOW(StandardWatchEventKinds.OVERFLOW);
567[warn]
568[warn] private WatchEvent.Kind<?> kind;
569[warn]
570[warn] EventType(WatchEvent.Kind<?> kind) {
571[warn] this.kind = kind;
572[warn] }
573[warn]
574[warn] public WatchEvent.Kind<?> getWatchEventKind() {
575[warn] return kind;
576[warn] }
577[warn] }
578[warn]
579[warn] private final EventType eventType;
580[warn] private final boolean isDirectory;
581[warn] private final Path path;
582[warn] private final FileHash hash;
583[warn] private final int count;
584[warn] private final Path rootPath;
585[warn]
586[warn] public DirectoryChangeEvent(
587[warn] EventType eventType,
588[warn] boolean isDirectory,
589[warn] Path path,
590[warn] FileHash hash,
591[warn] int count,
592[warn] Path rootPath) {
593[warn] this.eventType = eventType;
594[warn] this.isDirectory = isDirectory;
595[warn] this.hash = hash;
596[warn] this.path = path;
597[warn] this.count = count;
598[warn] this.rootPath = rootPath;
599[warn] }
600[warn]
601[warn] public EventType eventType() {
602[warn] return eventType;
603[warn] }
604[warn]
605[warn] public Path path() {
606[warn] return path;
607[warn] }
608[warn]
609[warn] public int count() {
610[warn] return count;
611[warn] }
612[warn]
613[warn] public Path rootPath() {
614[warn] return rootPath;
615[warn] }
616[warn]
617[warn] public boolean isDirectory() {
618[warn] return isDirectory;
619[warn] }
620[warn]
621[warn] public FileHash hash() {
622[warn] return hash;
623[warn] }
624[warn]
625[warn] @Override
626[warn] public boolean equals(Object o) {
627[warn] if (this == o) {
628[warn] return true;
629[warn] }
630[warn] if (o == null || getClass() != o.getClass()) {
631[warn] return false;
632[warn] }
633[warn]
634[warn] DirectoryChangeEvent that = (DirectoryChangeEvent) o;
635[warn]
636[warn] return count == that.count
637[warn] && eventType == that.eventType
638[warn] && isDirectory == that.isDirectory
639[warn] && Objects.equals(path, that.path)
640[warn] && Objects.equals(rootPath, that.rootPath)
641[warn] && Objects.equals(hash, that.hash);
642[warn] }
643[warn]
644[warn] @Override
645[warn] public int hashCode() {
646[warn] return Objects.hash(eventType, isDirectory, path, count, rootPath, hash);
647[warn] }
648[warn]
649[warn] @Override
650[warn] public String toString() {
651[warn] return "DirectoryChangeEvent{"
652[warn] + "eventType="
653[warn] + eventType
654[warn] + ", isDirectory="
655[warn] + isDirectory
656[warn] + ", path="
657[warn] + path
658[warn] + ", count="
659[warn] + count
660[warn] + ", rootPath="
661[warn] + rootPath
662[warn] + ", hash="
663[warn] + ((hash == null) ? "(null)" : hash) // don't want the printout to be too long
664[warn] + '}';
665[warn] }
666[warn] }
667[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:23:1: no comment
668[warn] public enum EventType {
669[warn]
670[warn] /* A new file was created */
671[warn] CREATE(StandardWatchEventKinds.ENTRY_CREATE),
672[warn]
673[warn] /* An existing file was modified */
674[warn] MODIFY(StandardWatchEventKinds.ENTRY_MODIFY),
675[warn]
676[warn] /* A file was deleted */
677[warn] DELETE(StandardWatchEventKinds.ENTRY_DELETE),
678[warn]
679[warn] /* An overflow occurred; some events were lost */
680[warn] OVERFLOW(StandardWatchEventKinds.OVERFLOW);
681[warn]
682[warn] private WatchEvent.Kind<?> kind;
683[warn]
684[warn] EventType(WatchEvent.Kind<?> kind) {
685[warn] this.kind = kind;
686[warn] }
687[warn]
688[warn] public WatchEvent.Kind<?> getWatchEventKind() {
689[warn] return kind;
690[warn] }
691[warn] }
692[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:55:1: no comment
693[warn] public DirectoryChangeEvent(
694[warn] EventType eventType,
695[warn] boolean isDirectory,
696[warn] Path path,
697[warn] FileHash hash,
698[warn] int count,
699[warn] Path rootPath) {
700[warn] this.eventType = eventType;
701[warn] this.isDirectory = isDirectory;
702[warn] this.hash = hash;
703[warn] this.path = path;
704[warn] this.count = count;
705[warn] this.rootPath = rootPath;
706[warn] }
707[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:78:1: no comment
708[warn] public int count() {
709[warn] return count;
710[warn] }
711[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:70:1: no comment
712[warn] public EventType eventType() {
713[warn] return eventType;
714[warn] }
715[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:90:1: no comment
716[warn] public FileHash hash() {
717[warn] return hash;
718[warn] }
719[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:86:1: no comment
720[warn] public boolean isDirectory() {
721[warn] return isDirectory;
722[warn] }
723[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:74:1: no comment
724[warn] public Path path() {
725[warn] return path;
726[warn] }
727[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:82:1: no comment
728[warn] public Path rootPath() {
729[warn] return rootPath;
730[warn] }
731[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:43:1: no comment
732[warn] public WatchEvent.Kind<?> getWatchEventKind() {
733[warn] return kind;
734[warn] }
735[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:26:1: no comment
736[warn] CREATE(StandardWatchEventKinds.ENTRY_CREATE)
737[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:32:1: no comment
738[warn] DELETE(StandardWatchEventKinds.ENTRY_DELETE)
739[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:29:1: no comment
740[warn] MODIFY(StandardWatchEventKinds.ENTRY_MODIFY)
741[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:35:1: no comment
742[warn] OVERFLOW(StandardWatchEventKinds.OVERFLOW)
743[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeListener.java:24:1: no comment
744[warn] static DirectoryChangeListener of(DirectoryChangeListener... listeners) {
745[warn] return new DirectoryChangeListener() {
746[warn] @Override
747[warn] public void onEvent(DirectoryChangeEvent event) throws IOException {
748[warn] for (DirectoryChangeListener listener : listeners) {
749[warn] listener.onEvent(event);
750[warn] }
751[warn] }
752[warn]
753[warn] @Override
754[warn] public void onException(Exception e) {
755[warn] for (DirectoryChangeListener listener : listeners) {
756[warn] listener.onException(e);
757[warn] }
758[warn] }
759[warn]
760[warn] @Override
761[warn] public void onIdle(int count) {
762[warn] for (DirectoryChangeListener listener : listeners) {
763[warn] listener.onIdle(count);
764[warn] }
765[warn] }
766[warn]
767[warn] @Override
768[warn] public boolean isWatching() {
769[warn] boolean anyWatching = false;
770[warn] for (DirectoryChangeListener listener : listeners) {
771[warn] anyWatching |= listener.isWatching();
772[warn] }
773[warn] return anyWatching;
774[warn] }
775[warn] };
776[warn] }
777[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeListener.java:65:1: no comment
778[warn] default void onIdle(int count) {
779[warn] // ignore onIdle by default
780[warn] }
781[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:172:1: no @return
782[warn] public static Builder builder() {
783[warn] return new Builder();
784[warn] }
785[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:214:1: no @return
786[warn] public CompletableFuture<Void> watchAsync() {
787[warn] return watchAsync(ForkJoinPool.commonPool());
788[warn] }
789[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:227:1: no @return
790[warn] public CompletableFuture<Void> watchAsync(Executor executor) {
791[warn] try {
792[warn] registerPaths();
793[warn] return CompletableFuture.supplyAsync(
794[warn] () -> {
795[warn] runEventLoop();
796[warn] return null;
797[warn] },
798[warn] executor);
799[warn] } catch (Throwable t) {
800[warn] CompletableFuture<Void> f = new CompletableFuture<>();
801[warn] f.completeExceptionally(t);
802[warn] return f;
803[warn] }
804[warn] }
805[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:46:1: no comment
806[warn] public class DirectoryWatcher {
807[warn]
808[warn] /**
809[warn] * A builder for a {@link DirectoryWatcher}. Use {@code DirectoryWatcher.builder()} to get a new
810[warn] * instance.
811[warn] */
812[warn] public static final class Builder {
813[warn] private List<Path> paths = Collections.emptyList();
814[warn] private DirectoryChangeListener listener = (event -> {});
815[warn] private Logger logger = null;
816[warn] private FileHasher fileHasher = FileHasher.DEFAULT_FILE_HASHER;
817[warn] private WatchService watchService = null;
818[warn] private FileTreeVisitor fileTreeVisitor = null;
819[warn]
820[warn] private Builder() {}
821[warn]
822[warn] /** Set multiple paths to watch. */
823[warn] public Builder paths(List<Path> paths) {
824[warn] this.paths = paths;
825[warn] return this;
826[warn] }
827[warn]
828[warn] /** Set a single path to watch. */
829[warn] public Builder path(Path path) {
830[warn] return paths(Collections.singletonList(path));
831[warn] }
832[warn]
833[warn] /** Set a listener that will be called when a directory change event occurs. */
834[warn] public Builder listener(DirectoryChangeListener listener) {
835[warn] this.listener = listener;
836[warn] return this;
837[warn] }
838[warn]
839[warn] /**
840[warn] * Set a {@link WatchService} implementation that will be used by the watcher.
841[warn] *
842[warn] * <p>By default, this detects your OS and either uses the native JVM watcher or the macOS
843[warn] * watcher.
844[warn] */
845[warn] public Builder watchService(WatchService watchService) {
846[warn] this.watchService = watchService;
847[warn] return this;
848[warn] }
849[warn]
850[warn] /**
851[warn] * Set a logger to be used by the watcher. This defaults to {@code
852[warn] * LoggerFactory.getLogger(DirectoryWatcher.class)}
853[warn] */
854[warn] public Builder logger(Logger logger) {
855[warn] this.logger = logger;
856[warn] return this;
857[warn] }
858[warn]
859[warn] /**
860[warn] * Defines whether file hashing should be used to catch duplicate events. Defaults to {@code
861[warn] * true}.
862[warn] */
863[warn] public Builder fileHashing(boolean enabled) {
864[warn] this.fileHasher = enabled ? FileHasher.DEFAULT_FILE_HASHER : null;
865[warn] return this;
866[warn] }
867[warn]
868[warn] /**
869[warn] * Defines the file hasher to be used by the watcher.
870[warn] *
871[warn] * <p>Note: will implicitly enable file hashing. Setting to null is equivalent to {@code
872[warn] * fileHashing(false)}
873[warn] */
874[warn] public Builder fileHasher(FileHasher fileHasher) {
875[warn] this.fileHasher = fileHasher;
876[warn] return this;
877[warn] }
878[warn]
879[warn] /** Defines the file tree visitor to be used by the watcher. */
880[warn] public Builder fileTreeVisitor(FileTreeVisitor fileTreeVisitor) {
881[warn] this.fileTreeVisitor = fileTreeVisitor;
882[warn] return this;
883[warn] }
884[warn]
885[warn] public DirectoryWatcher build() throws IOException {
886[warn] if (fileTreeVisitor == null) {
887[warn] fileTreeVisitor = FileTreeVisitor.DEFAULT_FILE_TREE_VISITOR;
888[warn] }
889[warn] if (watchService == null) {
890[warn] osDefaultWatchService(fileTreeVisitor);
891[warn] }
892[warn] if (logger == null) {
893[warn] staticLogger();
894[warn] }
895[warn] return new DirectoryWatcher(
896[warn] paths, listener, watchService, fileHasher, fileTreeVisitor, logger);
897[warn] }
898[warn]
899[warn] private Builder osDefaultWatchService(FileTreeVisitor fileTreeVisitor) throws IOException {
900[warn] boolean isMac = System.getProperty("os.name").toLowerCase().contains("mac");
901[warn] if (isMac) {
902[warn] return watchService(
903[warn] new MacOSXListeningWatchService(
904[warn] new MacOSXListeningWatchService.Config() {
905[warn] @Override
906[warn] public FileHasher fileHasher() {
907[warn] /**
908[warn] * Always return null here. When MacOSXListeningWatchService is used with
909[warn] * DirectoryWatcher, then the hashing should happen within DirectoryWatcher. If
910[warn] * users wish to override this then they must instantiate
911[warn] * MacOSXListeningWatchService and pass it to DirectoryWatcher.
912[warn] */
913[warn] return null;
914[warn] }
915[warn]
916[warn] @Override
917[warn] public FileTreeVisitor fileTreeVisitor() {
918[warn] return fileTreeVisitor;
919[warn] }
920[warn] }));
921[warn] } else {
922[warn] return watchService(FileSystems.getDefault().newWatchService());
923[warn] }
924[warn] }
925[warn]
926[warn] private Builder staticLogger() {
927[warn] return logger(LoggerFactory.getLogger(DirectoryWatcher.class));
928[warn] }
929[warn] }
930[warn]
931[warn] /** Get a new builder for a {@link DirectoryWatcher}. */
932[warn] public static Builder builder() {
933[warn] return new Builder();
934[warn] }
935[warn]
936[warn] private final Logger logger;
937[warn] private final WatchService watchService;
938[warn] private final List<Path> paths;
939[warn] private final boolean isMac;
940[warn] private final DirectoryChangeListener listener;
941[warn] private final FileHasher fileHasher;
942[warn] private final FileTreeVisitor fileTreeVisitor;
943[warn]
944[warn] private final Map<Path, Path> registeredPathToRootPath = new HashMap<>();;
945[warn] private final SortedMap<Path, FileHash> pathHashes = new ConcurrentSkipListMap<>();
946[warn] private final Set<Path> directories =
947[warn] Collections.newSetFromMap(new ConcurrentHashMap<Path, Boolean>());
948[warn] private final Map<WatchKey, Path> keyRoots = new ConcurrentHashMap<>();
949[warn]
950[warn] private volatile boolean closed = false;
951[warn]
952[warn] // set to null until we check if FILE_TREE is supported
953[warn] private Boolean fileTreeSupported = null;
954[warn]
955[warn] public DirectoryWatcher(
956[warn] List<Path> paths,
957[warn] DirectoryChangeListener listener,
958[warn] WatchService watchService,
959[warn] FileHasher fileHasher,
960[warn] FileTreeVisitor fileTreeVisitor,
961[warn] Logger logger) {
962[warn] this.paths = paths.stream().map(p -> p.toAbsolutePath()).collect(Collectors.toList());
963[warn] this.listener = listener;
964[warn] this.watchService = watchService;
965[warn] this.isMac = watchService instanceof MacOSXListeningWatchService;
966[warn] this.fileHasher = fileHasher;
967[warn] this.fileTreeVisitor = fileTreeVisitor;
968[warn] this.logger = logger;
969[warn] }
970[warn]
971[warn] /**
972[warn] * Asynchronously watch the directories using {@code ForkJoinPool.commonPool()} as the executor
973[warn] */
974[warn] public CompletableFuture<Void> watchAsync() {
975[warn] return watchAsync(ForkJoinPool.commonPool());
976[warn] }
977[warn]
978[warn] /**
979[warn] * Start watching for changes asynchronously.
980[warn] *
981[warn] * <p>The future completes when the listener stops listening or the watcher is closed.
982[warn] *
983[warn] * <p>This method will block until the watcher is initialized and successfully watching.
984[warn] *
985[warn] * @param executor the executor to use to watch asynchronously
986[warn] */
987[warn] public CompletableFuture<Void> watchAsync(Executor executor) {
988[warn] try {
989[warn] registerPaths();
990[warn] return CompletableFuture.supplyAsync(
991[warn] () -> {
992[warn] runEventLoop();
993[warn] return null;
994[warn] },
995[warn] executor);
996[warn] } catch (Throwable t) {
997[warn] CompletableFuture<Void> f = new CompletableFuture<>();
998[warn] f.completeExceptionally(t);
999[warn] return f;
1000[warn] }
1001[warn] }
1002[warn]
1003[warn] /**
1004[warn] * Watch for changes; block until the listener stops listening or the watcher is closed.
1005[warn] *
1006[warn] * @throws IllegalStateException if the directory watcher is closed when watch() is called.
1007[warn] */
1008[warn] public void watch() {
1009[warn] registerPaths();
1010[warn] runEventLoop();
1011[warn] }
1012[warn]
1013[warn] public Map<Path, FileHash> pathHashes() {
1014[warn] return Collections.unmodifiableMap(pathHashes);
1015[warn] }
1016[warn]
1017[warn] public DirectoryChangeListener getListener() {
1018[warn] return listener;
1019[warn] }
1020[warn]
1021[warn] public void close() throws IOException {
1022[warn] watchService.close();
1023[warn] closed = true;
1024[warn] }
1025[warn]
1026[warn] public boolean isClosed() {
1027[warn] return closed;
1028[warn] }
1029[warn]
1030[warn] private boolean isFileTreeSupported() {
1031[warn] if (fileTreeSupported == null) {
1032[warn] throw new IllegalStateException("fileTreeSupported not initialized");
1033[warn] }
1034[warn] return fileTreeSupported;
1035[warn] }
1036[warn]
1037[warn] private void registerPaths() {
1038[warn] try {
1039[warn] PathUtils.initWatcherState(paths, fileHasher, fileTreeVisitor, pathHashes, directories);
1040[warn]
1041[warn] for (Path path : paths) {
1042[warn] registerAll(path, path);
1043[warn] }
1044[warn] } catch (IOException e) {
1045[warn] throw new UncheckedIOException(e);
1046[warn] }
1047[warn] }
1048[warn]
1049[warn] private void runEventLoop() {
1050[warn] if (closed) {
1051[warn] throw new IllegalStateException("watcher already closed");
1052[warn] }
1053[warn] int eventCount = 0;
1054[warn] while (listener.isWatching()) {
1055[warn] // wait for key to be signalled
1056[warn] WatchKey key;
1057[warn] try {
1058[warn] key = watchService.poll();
1059[warn] if (key == null) {
1060[warn] listener.onIdle(eventCount);
1061[warn] key = watchService.take();
1062[warn] }
1063[warn] } catch (InterruptedException | ClosedWatchServiceException e) {
1064[warn] return;
1065[warn] }
1066[warn] for (WatchEvent<?> event : key.pollEvents()) {
1067[warn] eventCount++;
1068[warn] try {
1069[warn] WatchEvent.Kind<?> kind = event.kind();
1070[warn] // Context for directory entry event is the file name of entry
1071[warn] WatchEvent<Path> ev = PathUtils.cast(event);
1072[warn] int count = ev.count();
1073[warn] Path eventPath = ev.context();
1074[warn] if (!keyRoots.containsKey(key)) {
1075[warn] throw new IllegalStateException(
1076[warn] "WatchService returned key [" + key + "] but it was not found in keyRoots!");
1077[warn] }
1078[warn] Path registeredPath = keyRoots.get(key);
1079[warn] Path rootPath = registeredPathToRootPath.get(registeredPath);
1080[warn] Path childPath = eventPath == null ? null : keyRoots.get(key).resolve(eventPath);
1081[warn] logger.debug("{} [{}]", kind, childPath);
1082[warn] /*
1083[warn] * If a directory is created, and we're watching recursively, then register it
1084[warn] * and its sub-directories.
1085[warn] */
1086[warn] if (kind == OVERFLOW) {
1087[warn] onEvent(EventType.OVERFLOW, false, childPath, count, rootPath);
1088[warn] } else if (eventPath == null) {
1089[warn] throw new IllegalStateException("WatchService returned a null path for " + kind.name());
1090[warn] } else if (kind == ENTRY_CREATE) {
1091[warn] boolean isDirectory = Files.isDirectory(childPath, NOFOLLOW_LINKS);
1092[warn] if (isDirectory) {
1093[warn] if (!isFileTreeSupported()) {
1094[warn] registerAll(childPath, rootPath);
1095[warn] }
1096[warn] /*
1097[warn] * Our custom Mac service sends subdirectory changes but the Windows/Linux do
1098[warn] * not. Walk the file tree to make sure we send create events for any files that
1099[warn] * were created.
1100[warn] */
1101[warn] if (!isMac) {
1102[warn] fileTreeVisitor.recursiveVisitFiles(
1103[warn] childPath,
1104[warn] dir -> notifyCreateEvent(true, dir, count, rootPath),
1105[warn] file -> notifyCreateEvent(false, file, count, rootPath));
1106[warn] } else {
1107[warn] notifyCreateEvent(true, childPath, count, rootPath);
1108[warn] }
1109[warn] } else {
1110[warn] notifyCreateEvent(false, childPath, count, rootPath);
1111[warn] }
1112[warn] } else if (kind == ENTRY_MODIFY) {
1113[warn] boolean isDirectory = directories.contains(childPath);
1114[warn]
1115[warn] if (fileHasher == null) {
1116[warn] onEvent(EventType.MODIFY, isDirectory, childPath, count, rootPath);
1117[warn] } else {
1118[warn] /*
1119[warn] * Note that existingHash may be null due to the file being created before we
1120[warn] * start listening It's important we don't discard the event in this case
1121[warn] */
1122[warn] FileHash existingHash = pathHashes.get(childPath);
1123[warn]
1124[warn] /*
1125[warn] * newHash can be null when using File#delete() on windows - it generates MODIFY
1126[warn] * and DELETE in succession. In this case the MODIFY event can be safely ignored
1127[warn] */
1128[warn] FileHash newHash = PathUtils.hash(fileHasher, childPath);
1129[warn]
1130[warn] if (newHash != null && !newHash.equals(existingHash)) {
1131[warn] pathHashes.put(childPath, newHash);
1132[warn] onEvent(EventType.MODIFY, isDirectory, childPath, count, rootPath);
1133[warn] } else if (newHash == null) {
1134[warn] logger.debug(
1135[warn] "Failed to hash modified file [{}]. It may have been deleted.", childPath);
1136[warn] }
1137[warn] }
1138[warn] } else if (kind == ENTRY_DELETE) {
1139[warn] if (fileHasher == null) {
1140[warn] boolean isDirectory = directories.remove(childPath);
1141[warn] // hashing is disabled, so just notify on the path we got the event for
1142[warn] onEvent(EventType.DELETE, isDirectory, childPath, count, rootPath);
1143[warn] } else {
1144[warn] // hashing is enabled, so delete the hashes
1145[warn] for (Path path : PathUtils.subtreePaths(pathHashes, childPath)) {
1146[warn] boolean isDirectory = directories.remove(path);
1147[warn] pathHashes.remove(path);
1148[warn] onEvent(EventType.DELETE, isDirectory, path, count, rootPath);
1149[warn] }
1150[warn] }
1151[warn] }
1152[warn] } catch (Exception e) {
1153[warn] logger.debug("DirectoryWatcher got an exception while watching!", e);
1154[warn] listener.onException(e);
1155[warn] }
1156[warn] }
1157[warn] boolean valid = key.reset();
1158[warn] if (!valid) {
1159[warn] logger.debug("WatchKey for [{}] no longer valid; removing.", key.watchable());
1160[warn] // remove the key from the keyRoots
1161[warn] Path registeredPath = keyRoots.remove(key);
1162[warn]
1163[warn] // Also remove from the registeredPathToRootPath maps
1164[warn] registeredPathToRootPath.remove(registeredPath);
1165[warn]
1166[warn] // if there are no more keys left to watch, we can break out
1167[warn] if (keyRoots.isEmpty()) {
1168[warn] logger.debug("No more directories left to watch; terminating watcher.");
1169[warn] break;
1170[warn] }
1171[warn] }
1172[warn] }
1173[warn] try {
1174[warn] close();
1175[warn] } catch (IOException e) {
1176[warn] throw new UncheckedIOException(e);
1177[warn] }
1178[warn] }
1179[warn]
1180[warn] private void onEvent(
1181[warn] EventType eventType, boolean isDirectory, Path childPath, int count, Path rootPath)
1182[warn] throws IOException {
1183[warn] logger.debug("-> {} [{}] (isDirectory: {})", eventType, childPath, isDirectory);
1184[warn] FileHash hash = pathHashes.get(childPath);
1185[warn] listener.onEvent(
1186[warn] new DirectoryChangeEvent(eventType, isDirectory, childPath, hash, count, rootPath));
1187[warn] }
1188[warn]
1189[warn] private void registerAll(final Path start, final Path context) throws IOException {
1190[warn] if (!Boolean.FALSE.equals(fileTreeSupported)) {
1191[warn] // Try using FILE_TREE modifier since we aren't certain that it's unsupported
1192[warn] try {
1193[warn] register(start, true, context);
1194[warn] // Assume FILE_TREE is supported
1195[warn] fileTreeSupported = true;
1196[warn] } catch (UnsupportedOperationException e) {
1197[warn] // UnsupportedOperationException should only happen if FILE_TREE is unsupported
1198[warn] logger.debug("Assuming ExtendedWatchEventModifier.FILE_TREE is not supported", e);
1199[warn] fileTreeSupported = false;
1200[warn] // If we failed to use the FILE_TREE modifier, try again without
1201[warn] registerAll(start, context);
1202[warn] }
1203[warn] } else {
1204[warn] // Since FILE_TREE is unsupported, register root directory and sub-directories
1205[warn] fileTreeVisitor.recursiveVisitFiles(start, dir -> register(dir, false, context), file -> {});
1206[warn] }
1207[warn] }
1208[warn]
1209[warn] // Internal method to be used by registerAll
1210[warn] private void register(Path directory, boolean useFileTreeModifier, Path context)
1211[warn] throws IOException {
1212[warn] logger.debug("Registering [{}].", directory);
1213[warn] Watchable watchable = isMac ? new WatchablePath(directory) : directory;
1214[warn] WatchEvent.Modifier[] modifiers =
1215[warn] useFileTreeModifier
1216[warn] ? new WatchEvent.Modifier[] {ExtendedWatchEventModifier.FILE_TREE}
1217[warn] : new WatchEvent.Modifier[] {};
1218[warn] WatchEvent.Kind<?>[] kinds =
1219[warn] new WatchEvent.Kind<?>[] {ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY};
1220[warn] WatchKey watchKey = watchable.register(watchService, kinds, modifiers);
1221[warn] keyRoots.put(watchKey, directory);
1222[warn] registeredPathToRootPath.put(directory, context);
1223[warn] }
1224[warn]
1225[warn] private void notifyCreateEvent(boolean isDirectory, Path path, int count, Path rootPath)
1226[warn] throws IOException {
1227[warn] if (fileHasher != null) {
1228[warn] FileHash newHash = PathUtils.hash(fileHasher, path);
1229[warn] if (newHash == null) {
1230[warn] // Hashing could fail for locked files on Windows.
1231[warn] // Skip notification only if we confirm the file does not exist.
1232[warn] if (Files.notExists(path)) {
1233[warn] logger.debug("Failed to hash created file [{}]. It may have been deleted.", path);
1234[warn] // Skip notifying the event.
1235[warn] return;
1236[warn] } else {
1237[warn] // Just warn here and continue to notify the event.
1238[warn] logger.debug("Failed to hash created file [{}]. It may be locked.", path);
1239[warn] }
1240[warn] } else {
1241[warn] FileHash oldHash = pathHashes.put(path, newHash);
1242[warn] if (oldHash != null) {
1243[warn] if (oldHash == newHash) {
1244[warn] // Creates might occur just before we traverse and notify for files in a new directory.
1245[warn] // We generally want to skip the duplicate if the hash has not changed.
1246[warn] logger.debug("Skipping duplicate create event for file [{}].", path);
1247[warn] return;
1248[warn] } else {
1249[warn] // This might happen if events were discarded and perhaps we missed a DELETE event.
1250[warn] logger.debug("Sending MODIFY instead of CREATE for existing hashed file [{}].", path);
1251[warn] onEvent(EventType.MODIFY, isDirectory, path, count, rootPath);
1252[warn] return;
1253[warn] }
1254[warn] }
1255[warn] }
1256[warn] }
1257[warn] if (isDirectory) {
1258[warn] directories.add(path);
1259[warn] }
1260[warn] onEvent(EventType.CREATE, isDirectory, path, count, rootPath);
1261[warn] }
1262[warn] }
1263[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:195:1: no comment
1264[warn] public DirectoryWatcher(
1265[warn] List<Path> paths,
1266[warn] DirectoryChangeListener listener,
1267[warn] WatchService watchService,
1268[warn] FileHasher fileHasher,
1269[warn] FileTreeVisitor fileTreeVisitor,
1270[warn] Logger logger) {
1271[warn] this.paths = paths.stream().map(p -> p.toAbsolutePath()).collect(Collectors.toList());
1272[warn] this.listener = listener;
1273[warn] this.watchService = watchService;
1274[warn] this.isMac = watchService instanceof MacOSXListeningWatchService;
1275[warn] this.fileHasher = fileHasher;
1276[warn] this.fileTreeVisitor = fileTreeVisitor;
1277[warn] this.logger = logger;
1278[warn] }
1279[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:261:1: no comment
1280[warn] public void close() throws IOException {
1281[warn] watchService.close();
1282[warn] closed = true;
1283[warn] }
1284[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:257:1: no comment
1285[warn] public DirectoryChangeListener getListener() {
1286[warn] return listener;
1287[warn] }
1288[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:266:1: no comment
1289[warn] public boolean isClosed() {
1290[warn] return closed;
1291[warn] }
1292[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:253:1: no comment
1293[warn] public Map<Path, FileHash> pathHashes() {
1294[warn] return Collections.unmodifiableMap(pathHashes);
1295[warn] }
1296[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:63:1: no @param for paths
1297[warn] public Builder paths(List<Path> paths) {
1298[warn] this.paths = paths;
1299[warn] return this;
1300[warn] }
1301[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:69:1: no @param for path
1302[warn] public Builder path(Path path) {
1303[warn] return paths(Collections.singletonList(path));
1304[warn] }
1305[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:74:1: no @param for listener
1306[warn] public Builder listener(DirectoryChangeListener listener) {
1307[warn] this.listener = listener;
1308[warn] return this;
1309[warn] }
1310[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:85:1: no @param for watchService
1311[warn] public Builder watchService(WatchService watchService) {
1312[warn] this.watchService = watchService;
1313[warn] return this;
1314[warn] }
1315[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:94:1: no @param for logger
1316[warn] public Builder logger(Logger logger) {
1317[warn] this.logger = logger;
1318[warn] return this;
1319[warn] }
1320[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:103:1: no @param for enabled
1321[warn] public Builder fileHashing(boolean enabled) {
1322[warn] this.fileHasher = enabled ? FileHasher.DEFAULT_FILE_HASHER : null;
1323[warn] return this;
1324[warn] }
1325[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:114:1: no @param for fileHasher
1326[warn] public Builder fileHasher(FileHasher fileHasher) {
1327[warn] this.fileHasher = fileHasher;
1328[warn] return this;
1329[warn] }
1330[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:120:1: no @param for fileTreeVisitor
1331[warn] public Builder fileTreeVisitor(FileTreeVisitor fileTreeVisitor) {
1332[warn] this.fileTreeVisitor = fileTreeVisitor;
1333[warn] return this;
1334[warn] }
1335[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:125:1: no comment
1336[warn] public DirectoryWatcher build() throws IOException {
1337[warn] if (fileTreeVisitor == null) {
1338[warn] fileTreeVisitor = FileTreeVisitor.DEFAULT_FILE_TREE_VISITOR;
1339[warn] }
1340[warn] if (watchService == null) {
1341[warn] osDefaultWatchService(fileTreeVisitor);
1342[warn] }
1343[warn] if (logger == null) {
1344[warn] staticLogger();
1345[warn] }
1346[warn] return new DirectoryWatcher(
1347[warn] paths, listener, watchService, fileHasher, fileTreeVisitor, logger);
1348[warn] }
1349[warn] /build/repo/core/src/main/java/io/methvin/watcher/hashing/FileHash.java:40:1: no comment
1350[warn] public static FileHash directory() {
1351[warn] return DIRECTORY;
1352[warn] }
1353[warn] /build/repo/core/src/main/java/io/methvin/watcher/hashing/FileHash.java:30:1: no comment
1354[warn] public static FileHash fromBytes(byte[] value) {
1355[warn] return new ByteArrayFileHash(Arrays.copyOf(value, value.length));
1356[warn] }
1357[warn] /build/repo/core/src/main/java/io/methvin/watcher/hashing/FileHash.java:34:1: no comment
1358[warn] public static FileHash fromLong(long value) {
1359[warn] ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
1360[warn] buffer.putLong(value);
1361[warn] return new ByteArrayFileHash(buffer.array());
1362[warn] }
1363[warn] /build/repo/core/src/main/java/io/methvin/watcher/hashing/FileHasher.java:63:1: no comment
1364[warn] FileHash hash(Path path) throws IOException;
1365[warn] /build/repo/core/src/main/java/io/methvin/watcher/visitor/FileTreeVisitor.java:7:1: no comment
1366[warn] public interface FileTreeVisitor {
1367[warn]
1368[warn] /** The default file tree visitor instance, which uses Files.walkFileTree. */
1369[warn] FileTreeVisitor DEFAULT_FILE_TREE_VISITOR = new DefaultFileTreeVisitor();
1370[warn]
1371[warn] interface Callback {
1372[warn] void call(Path p) throws IOException;
1373[warn] }
1374[warn]
1375[warn] void recursiveVisitFiles(Path file, Callback onDirectory, Callback onFile) throws IOException;
1376[warn] }
1377[warn] /build/repo/core/src/main/java/io/methvin/watcher/visitor/FileTreeVisitor.java:12:1: no comment
1378[warn] interface Callback {
1379[warn] void call(Path p) throws IOException;
1380[warn] }
1381[warn] /build/repo/core/src/main/java/io/methvin/watcher/visitor/FileTreeVisitor.java:13:1: no comment
1382[warn] void call(Path p) throws IOException;
1383[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/FSEventStreamRef.java:18:1: no comment
1384[warn] public class FSEventStreamRef extends PointerByReference {}
1385[warn] /build/repo/core/src/main/java/io/methvin/watchservice/MacOSXListeningWatchService.java:172:1: no comment
1386[warn] public static class CFRunLoopThread extends Thread {
1387[warn] private final FSEventStreamRef streamRef;
1388[warn] private CFRunLoopRef runLoopRef;
1389[warn] private boolean isClosed = false;
1390[warn]
1391[warn] public CFRunLoopThread(FSEventStreamRef streamRef, File file) {
1392[warn] super("WatchService for " + file);
1393[warn] this.streamRef = streamRef;
1394[warn] }
1395[warn]
1396[warn] @Override
1397[warn] public void run() {
1398[warn] synchronized (streamRef) {
1399[warn] if (isClosed) return;
1400[warn] runLoopRef = CarbonAPI.INSTANCE.CFRunLoopGetCurrent();
1401[warn] final CFStringRef runLoopMode = CFStringRef.toCFString("kCFRunLoopDefaultMode");
1402[warn] CarbonAPI.INSTANCE.FSEventStreamScheduleWithRunLoop(streamRef, runLoopRef, runLoopMode);
1403[warn] CarbonAPI.INSTANCE.FSEventStreamStart(streamRef);
1404[warn] }
1405[warn] CarbonAPI.INSTANCE.CFRunLoopRun();
1406[warn] }
1407[warn]
1408[warn] public void close() {
1409[warn] synchronized (streamRef) {
1410[warn] if (isClosed) return;
1411[warn] if (runLoopRef != null) {
1412[warn] CarbonAPI.INSTANCE.CFRunLoopStop(runLoopRef);
1413[warn] CarbonAPI.INSTANCE.FSEventStreamStop(streamRef);
1414[warn] CarbonAPI.INSTANCE.FSEventStreamInvalidate(streamRef);
1415[warn] }
1416[warn] CarbonAPI.INSTANCE.FSEventStreamRelease(streamRef);
1417[warn] isClosed = true;
1418[warn] }
1419[warn] }
1420[warn] }
1421[warn] /build/repo/core/src/main/java/io/methvin/watchservice/MacOSXListeningWatchService.java:118:1: no comment
1422[warn] public MacOSXListeningWatchService() {
1423[warn] this(new Config() {});
1424[warn] }
1425[warn] /build/repo/core/src/main/java/io/methvin/watchservice/MacOSXListeningWatchService.java:109:1: no comment
1426[warn] public MacOSXListeningWatchService(Config config) {
1427[warn] this.latency = config.latency();
1428[warn] this.queueSize = config.queueSize();
1429[warn] this.fileTreeVisitor = config.fileTreeVisitor();
1430[warn] FileHasher hasher = config.fileHasher();
1431[warn] this.fileLevelEvents = hasher == null || config.fileLevelEvents();
1432[warn] this.fileHasher = hasher == null ? INCREMENTING_FILE_HASHER : hasher;
1433[warn] }
1434[warn] /build/repo/core/src/main/java/io/methvin/watchservice/AbstractWatchService.java:69:1: no @param for key
1435[warn] public void cancelled(AbstractWatchKey key) {}
1436[warn] /build/repo/core/src/main/java/io/methvin/watchservice/MacOSXListeningWatchService.java:217:1: no comment
1437[warn] public synchronized void close(
1438[warn] CFRunLoopThread runLoopThread, CarbonAPI.FSEventStreamCallback callback, Path path) {
1439[warn] threadList.remove(runLoopThread);
1440[warn] callbackList.remove(callback);
1441[warn] pathsWatching.remove(path);
1442[warn] runLoopThread.close();
1443[warn] }
1444[warn] /build/repo/core/src/main/java/io/methvin/watchservice/AbstractWatchService.java:57:1: no @return
1445[warn] public boolean isOpen() {
1446[warn] return open.get();
1447[warn] }
1448[warn] /build/repo/core/src/main/java/io/methvin/watchservice/AbstractWatchService.java:52:1: no @param for watchable
1449[warn] public abstract AbstractWatchKey register(
1450[warn] WatchablePath watchable, Iterable<? extends WatchEvent.Kind<?>> eventTypes)
1451[warn] throws IOException;
1452[info] 100 warnings
1453[warn] Loading source file DirectoryChangeEvent.java...
1454[warn] Loading source file DirectoryWatcher.java...
1455[warn] Loading source file DirectoryChangeListener.java...
1456[warn] Loading source file PathUtils.java...
1457[warn] Loading source file OnTimeoutListener.java...
1458[warn] Loading source file AbstractWatchKey.java...
1459[warn] Loading source file MacOSXListeningWatchService.java...
1460[warn] Loading source file WatchablePath.java...
1461[warn] Loading source file MacOSXWatchKey.java...
1462[warn] Loading source file AbstractWatchService.java...
1463[warn] Loading source file DefaultFileTreeVisitor.java...
1464[warn] Loading source file FileTreeVisitor.java...
1465[warn] Loading source file ChangeSetImpl.java...
1466[warn] Loading source file ChangeSetEntry.java...
1467[warn] Loading source file ChangeSetBuilder.java...
1468[warn] Loading source file ChangeSetListener.java...
1469[warn] Loading source file ChangeSet.java...
1470[warn] Loading source file ByteArrayFileHash.java...
1471[warn] Loading source file FileHasher.java...
1472[warn] Loading source file Murmur3F.java...
1473[warn] Loading source file FileHash.java...
1474[warn] Loading source file CFIndex.java...
1475[warn] Loading source file FSEventStreamRef.java...
1476[warn] Loading source file CFAllocatorRef.java...
1477[warn] Loading source file CarbonAPI.java...
1478[warn] Loading source file CFArrayRef.java...
1479[warn] Loading source file CFRunLoopRef.java...
1480[warn] Loading source file CFStringRef.java...
1481[warn] Constructing Javadoc information...
1482[warn] Building index for all the packages and classes...
1483[warn] Standard Doclet version 17.0.8+7
1484[warn] Building tree for all the packages and classes...
1485[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/jna/CarbonAPI.html...
1486[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/jna/CarbonAPI.FSEventStreamCallback.html...
1487[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/jna/CFAllocatorRef.html...
1488[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/jna/CFArrayRef.html...
1489[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/jna/CFIndex.html...
1490[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/jna/CFRunLoopRef.html...
1491[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/jna/CFStringRef.html...
1492[warn] Generating /build/repo/core/target/api/io/methvin/watcher/changeset/ChangeSet.html...
1493[warn] Generating /build/repo/core/target/api/io/methvin/watcher/changeset/ChangeSetEntry.html...
1494[warn] Generating /build/repo/core/target/api/io/methvin/watcher/changeset/ChangeSetListener.html...
1495[warn] Generating /build/repo/core/target/api/io/methvin/watcher/visitor/DefaultFileTreeVisitor.html...
1496[warn] Generating /build/repo/core/target/api/io/methvin/watcher/DirectoryChangeEvent.html...
1497[warn] Generating /build/repo/core/target/api/io/methvin/watcher/DirectoryChangeEvent.EventType.html...
1498[warn] Generating /build/repo/core/target/api/io/methvin/watcher/DirectoryChangeListener.html...
1499[warn] Generating /build/repo/core/target/api/io/methvin/watcher/DirectoryWatcher.html...
1500[warn] Generating /build/repo/core/target/api/io/methvin/watcher/DirectoryWatcher.Builder.html...
1501[warn] Generating /build/repo/core/target/api/io/methvin/watcher/hashing/FileHash.html...
1502[warn] Generating /build/repo/core/target/api/io/methvin/watcher/hashing/FileHasher.html...
1503[warn] Generating /build/repo/core/target/api/io/methvin/watcher/visitor/FileTreeVisitor.html...
1504[warn] Generating /build/repo/core/target/api/io/methvin/watcher/visitor/FileTreeVisitor.Callback.html...
1505[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/jna/FSEventStreamRef.html...
1506[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/MacOSXListeningWatchService.html...
1507[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/MacOSXListeningWatchService.CFRunLoopThread.html...
1508[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/MacOSXListeningWatchService.Config.html...
1509[warn] Generating /build/repo/core/target/api/io/methvin/watcher/hashing/Murmur3F.html...
1510[warn] Generating /build/repo/core/target/api/io/methvin/watcher/OnTimeoutListener.html...
1511[warn] Generating /build/repo/core/target/api/io/methvin/watcher/PathUtils.html...
1512[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/WatchablePath.html...
1513[warn] Generating /build/repo/core/target/api/io/methvin/watcher/package-summary.html...
1514[warn] Generating /build/repo/core/target/api/io/methvin/watcher/package-tree.html...
1515[warn] Generating /build/repo/core/target/api/io/methvin/watcher/changeset/package-summary.html...
1516[warn] Generating /build/repo/core/target/api/io/methvin/watcher/changeset/package-tree.html...
1517[warn] Generating /build/repo/core/target/api/io/methvin/watcher/hashing/package-summary.html...
1518[warn] Generating /build/repo/core/target/api/io/methvin/watcher/hashing/package-tree.html...
1519[warn] Generating /build/repo/core/target/api/io/methvin/watcher/visitor/package-summary.html...
1520[warn] Generating /build/repo/core/target/api/io/methvin/watcher/visitor/package-tree.html...
1521[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/package-summary.html...
1522[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/package-tree.html...
1523[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/jna/package-summary.html...
1524[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/jna/package-tree.html...
1525[warn] Generating /build/repo/core/target/api/constant-values.html...
1526[warn] Generating /build/repo/core/target/api/serialized-form.html...
1527[warn] Generating /build/repo/core/target/api/overview-tree.html...
1528[warn] Generating /build/repo/core/target/api/index.html...
1529[warn] Building index for all classes...
1530[warn] Generating /build/repo/core/target/api/allclasses-index.html...
1531[warn] Generating /build/repo/core/target/api/allpackages-index.html...
1532[warn] Generating /build/repo/core/target/api/index-all.html...
1533[warn] Generating /build/repo/core/target/api/overview-summary.html...
1534[warn] Generating /build/repo/core/target/api/help-doc.html...
1535[info] Main Java API documentation successful.
1536[info] compiling 6 Java sources to /build/repo/core/target/test-classes ...
1537[warn] /build/repo/core/src/test/java/io/methvin/watcher/DirectoryWatcherOnDiskTest.java:557:1: unchecked generic array creation for varargs parameter of type java.util.List<java.nio.file.Path>[]
1538[warn] updatePaths(paths1)
1539[warn] /build/repo/core/src/test/java/io/methvin/watcher/DirectoryWatcherOnDiskTest.java:562:1: unchecked generic array creation for varargs parameter of type java.util.List<java.nio.file.Path>[]
1540[warn] updatePaths(paths2, paths3)
1541[warn] /build/repo/core/src/test/java/io/methvin/watcher/DirectoryWatcherOnDiskTest.java:762:1: Possible heap pollution from parameterized vararg type java.util.List<java.nio.file.Path>
1542[warn] List<Path>... paths
1543[warn] /build/repo/core/src/test/java/io/methvin/watchservice/FileSystem.java:89:1: fileAppend(java.lang.String,java.lang.String) in org.codehaus.plexus.util.FileUtils has been deprecated
1544[warn] FileUtils.fileAppend
1545[info] done compiling
1546[info] Wrote /build/repo/core/target/directory-watcher-0.18.0.pom
1547[info] Main Java API documentation to /build/repo/core/target/api...
1548[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:18:1: no comment
1549[warn] public interface CarbonAPI extends Library {
1550[warn] // sbt uses JNA 4.5.0, so use JNA 4.x's API
1551[warn] CarbonAPI INSTANCE = (CarbonAPI) Native.loadLibrary("Carbon", CarbonAPI.class);
1552[warn]
1553[warn] CFArrayRef CFArrayCreate(
1554[warn] CFAllocatorRef allocator, // always set to Pointer.NULL
1555[warn] Pointer[] values,
1556[warn] CFIndex numValues,
1557[warn] Void callBacks // always set to Pointer.NULL
1558[warn] );
1559[warn]
1560[warn] CFStringRef CFStringCreateWithCharacters(
1561[warn] Void alloc, // always pass NULL
1562[warn] char[] chars,
1563[warn] CFIndex numChars);
1564[warn]
1565[warn] public FSEventStreamRef FSEventStreamCreate(
1566[warn] Pointer v, // always use Pointer.NULL
1567[warn] FSEventStreamCallback callback,
1568[warn] Pointer context, // always use Pointer.NULL
1569[warn] CFArrayRef pathsToWatch,
1570[warn] long sinceWhen, // use -1 for events since now
1571[warn] double latency, // in seconds
1572[warn] int flags // 0 is good for now
1573[warn] );
1574[warn]
1575[warn] boolean FSEventStreamStart(FSEventStreamRef streamRef);
1576[warn]
1577[warn] void FSEventStreamStop(FSEventStreamRef streamRef);
1578[warn]
1579[warn] void FSEventStreamScheduleWithRunLoop(
1580[warn] FSEventStreamRef streamRef, CFRunLoopRef runLoop, CFStringRef runLoopMode);
1581[warn]
1582[warn] void FSEventStreamUnscheduleFromRunLoop(
1583[warn] FSEventStreamRef streamRef, CFRunLoopRef runLoop, CFStringRef runLoopMode);
1584[warn]
1585[warn] void FSEventStreamInvalidate(FSEventStreamRef streamRef);
1586[warn]
1587[warn] void FSEventStreamRelease(FSEventStreamRef streamRef);
1588[warn]
1589[warn] CFRunLoopRef CFRunLoopGetCurrent();
1590[warn]
1591[warn] void CFRunLoopRun();
1592[warn]
1593[warn] void CFRunLoopStop(CFRunLoopRef runLoopRef);
1594[warn]
1595[warn] public interface FSEventStreamCallback extends Callback {
1596[warn] @SuppressWarnings({"UnusedDeclaration"})
1597[warn] void invoke(
1598[warn] FSEventStreamRef streamRef,
1599[warn] Pointer clientCallBackInfo,
1600[warn] NativeLong numEvents,
1601[warn] Pointer eventPaths,
1602[warn] Pointer eventFlags,
1603[warn] Pointer eventIds);
1604[warn] }
1605[warn] }
1606[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:64:1: no comment
1607[warn] public interface FSEventStreamCallback extends Callback {
1608[warn] @SuppressWarnings({"UnusedDeclaration"})
1609[warn] void invoke(
1610[warn] FSEventStreamRef streamRef,
1611[warn] Pointer clientCallBackInfo,
1612[warn] NativeLong numEvents,
1613[warn] Pointer eventPaths,
1614[warn] Pointer eventFlags,
1615[warn] Pointer eventIds);
1616[warn] }
1617[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:20:1: no comment
1618[warn] CarbonAPI INSTANCE = (CarbonAPI) Native.loadLibrary("Carbon", CarbonAPI.class);
1619[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:22:1: no comment
1620[warn] CFArrayRef CFArrayCreate(
1621[warn] CFAllocatorRef allocator, // always set to Pointer.NULL
1622[warn] Pointer[] values,
1623[warn] CFIndex numValues,
1624[warn] Void callBacks // always set to Pointer.NULL
1625[warn] );
1626[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:58:1: no comment
1627[warn] CFRunLoopRef CFRunLoopGetCurrent();
1628[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:60:1: no comment
1629[warn] void CFRunLoopRun();
1630[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:62:1: no comment
1631[warn] void CFRunLoopStop(CFRunLoopRef runLoopRef);
1632[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:29:1: no comment
1633[warn] CFStringRef CFStringCreateWithCharacters(
1634[warn] Void alloc, // always pass NULL
1635[warn] char[] chars,
1636[warn] CFIndex numChars);
1637[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:34:1: no comment
1638[warn] public FSEventStreamRef FSEventStreamCreate(
1639[warn] Pointer v, // always use Pointer.NULL
1640[warn] FSEventStreamCallback callback,
1641[warn] Pointer context, // always use Pointer.NULL
1642[warn] CFArrayRef pathsToWatch,
1643[warn] long sinceWhen, // use -1 for events since now
1644[warn] double latency, // in seconds
1645[warn] int flags // 0 is good for now
1646[warn] );
1647[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:54:1: no comment
1648[warn] void FSEventStreamInvalidate(FSEventStreamRef streamRef);
1649[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:56:1: no comment
1650[warn] void FSEventStreamRelease(FSEventStreamRef streamRef);
1651[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:48:1: no comment
1652[warn] void FSEventStreamScheduleWithRunLoop(
1653[warn] FSEventStreamRef streamRef, CFRunLoopRef runLoop, CFStringRef runLoopMode);
1654[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:44:1: no comment
1655[warn] boolean FSEventStreamStart(FSEventStreamRef streamRef);
1656[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:46:1: no comment
1657[warn] void FSEventStreamStop(FSEventStreamRef streamRef);
1658[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:51:1: no comment
1659[warn] void FSEventStreamUnscheduleFromRunLoop(
1660[warn] FSEventStreamRef streamRef, CFRunLoopRef runLoop, CFStringRef runLoopMode);
1661[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CarbonAPI.java:66:1: no comment
1662[warn] @SuppressWarnings({"UnusedDeclaration"})
1663[warn] void invoke(
1664[warn] FSEventStreamRef streamRef,
1665[warn] Pointer clientCallBackInfo,
1666[warn] NativeLong numEvents,
1667[warn] Pointer eventPaths,
1668[warn] Pointer eventFlags,
1669[warn] Pointer eventIds);
1670[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CFAllocatorRef.java:18:1: no comment
1671[warn] public class CFAllocatorRef extends PointerByReference {}
1672[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CFArrayRef.java:18:1: no comment
1673[warn] public class CFArrayRef extends PointerByReference {}
1674[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CFIndex.java:18:1: no comment
1675[warn] public class CFIndex extends NativeLong {
1676[warn] private static final long serialVersionUID = 0;
1677[warn]
1678[warn] public static CFIndex valueOf(int i) {
1679[warn] CFIndex idx = new CFIndex();
1680[warn] idx.setValue(i);
1681[warn] return idx;
1682[warn] }
1683[warn] }
1684[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CFIndex.java:21:1: no comment
1685[warn] public static CFIndex valueOf(int i) {
1686[warn] CFIndex idx = new CFIndex();
1687[warn] idx.setValue(i);
1688[warn] return idx;
1689[warn] }
1690[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CFRunLoopRef.java:18:1: no comment
1691[warn] public class CFRunLoopRef extends PointerByReference {}
1692[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CFStringRef.java:18:1: no comment
1693[warn] public class CFStringRef extends PointerByReference {
1694[warn]
1695[warn] public static CFStringRef toCFString(String s) {
1696[warn] final char[] chars = s.toCharArray();
1697[warn] int length = chars.length;
1698[warn] return CarbonAPI.INSTANCE.CFStringCreateWithCharacters(null, chars, CFIndex.valueOf(length));
1699[warn] }
1700[warn] }
1701[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/CFStringRef.java:20:1: no comment
1702[warn] public static CFStringRef toCFString(String s) {
1703[warn] final char[] chars = s.toCharArray();
1704[warn] int length = chars.length;
1705[warn] return CarbonAPI.INSTANCE.CFStringCreateWithCharacters(null, chars, CFIndex.valueOf(length));
1706[warn] }
1707[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSet.java:5:1: no comment
1708[warn] public interface ChangeSet {
1709[warn] Set<ChangeSetEntry> created();
1710[warn]
1711[warn] Set<ChangeSetEntry> modified();
1712[warn]
1713[warn] Set<ChangeSetEntry> deleted();
1714[warn] }
1715[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSet.java:6:1: no comment
1716[warn] Set<ChangeSetEntry> created();
1717[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSet.java:10:1: no comment
1718[warn] Set<ChangeSetEntry> deleted();
1719[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSet.java:8:1: no comment
1720[warn] Set<ChangeSetEntry> modified();
1721[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSetEntry.java:7:1: no comment
1722[warn] public final class ChangeSetEntry {
1723[warn]
1724[warn] private final Path path;
1725[warn] private final boolean isDirectory;
1726[warn] private final FileHash hash;
1727[warn] private final Path rootPath;
1728[warn]
1729[warn] ChangeSetEntry(Path path, boolean isDirectory, FileHash hash, Path rootPath) {
1730[warn] this.path = path;
1731[warn] this.isDirectory = isDirectory;
1732[warn] this.hash = hash;
1733[warn] this.rootPath = rootPath;
1734[warn] }
1735[warn]
1736[warn] public Path path() {
1737[warn] return path;
1738[warn] }
1739[warn]
1740[warn] public boolean isDirectory() {
1741[warn] return isDirectory;
1742[warn] }
1743[warn]
1744[warn] public FileHash hash() {
1745[warn] return hash;
1746[warn] }
1747[warn]
1748[warn] public Path rootPath() {
1749[warn] return rootPath;
1750[warn] }
1751[warn]
1752[warn] @Override
1753[warn] public boolean equals(Object o) {
1754[warn] if (this == o) {
1755[warn] return true;
1756[warn] }
1757[warn] if (o == null || getClass() != o.getClass()) {
1758[warn] return false;
1759[warn] }
1760[warn]
1761[warn] ChangeSetEntry that = (ChangeSetEntry) o;
1762[warn]
1763[warn] return isDirectory == that.isDirectory
1764[warn] && path.equals(that.path)
1765[warn] && hash.equals(that.hash)
1766[warn] && rootPath.equals(that.rootPath);
1767[warn] }
1768[warn]
1769[warn] @Override
1770[warn] public int hashCode() {
1771[warn] return Objects.hash(path, isDirectory, rootPath, hash);
1772[warn] }
1773[warn] }
1774[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSetEntry.java:29:1: no comment
1775[warn] public FileHash hash() {
1776[warn] return hash;
1777[warn] }
1778[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSetEntry.java:25:1: no comment
1779[warn] public boolean isDirectory() {
1780[warn] return isDirectory;
1781[warn] }
1782[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSetEntry.java:21:1: no comment
1783[warn] public Path path() {
1784[warn] return path;
1785[warn] }
1786[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSetEntry.java:33:1: no comment
1787[warn] public Path rootPath() {
1788[warn] return rootPath;
1789[warn] }
1790[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeListener.java:61:1: no @return
1791[warn] default boolean isWatching() {
1792[warn] return true;
1793[warn] }
1794[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeListener.java:72:1: no @param for e
1795[warn] default void onException(Exception e) {
1796[warn] // Ignore exceptions by default (they will be logged by the watcher)
1797[warn] }
1798[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSetListener.java:10:1: no comment
1799[warn] public final class ChangeSetListener implements DirectoryChangeListener {
1800[warn]
1801[warn] private Map<Path, ChangeSetBuilder> changeBuilders = new HashMap<>();
1802[warn]
1803[warn] private final Object lock = new Object() {};
1804[warn]
1805[warn] @Override
1806[warn] public void onEvent(DirectoryChangeEvent event) {
1807[warn] Path rootPath = event.rootPath();
1808[warn] Path path = event.path();
1809[warn]
1810[warn] synchronized (lock) {
1811[warn] // Maintain a ChangeSet per rootPath
1812[warn] ChangeSetBuilder builder = changeBuilders.get(rootPath);
1813[warn] if (builder == null) {
1814[warn] builder = new ChangeSetBuilder();
1815[warn] changeBuilders.put(rootPath, builder);
1816[warn] }
1817[warn]
1818[warn] ChangeSetEntry entry =
1819[warn] new ChangeSetEntry(path, event.isDirectory(), event.hash(), event.rootPath());
1820[warn]
1821[warn] switch (event.eventType()) {
1822[warn] case CREATE:
1823[warn] builder.addCreated(entry);
1824[warn] break;
1825[warn] case MODIFY:
1826[warn] builder.addModified(entry);
1827[warn] break;
1828[warn] case DELETE:
1829[warn] builder.addDeleted(entry);
1830[warn] break;
1831[warn] case OVERFLOW:
1832[warn] throw new IllegalStateException("OVERFLOW not yet handled");
1833[warn] }
1834[warn] }
1835[warn] }
1836[warn]
1837[warn] public Map<Path, ChangeSet> getChangeSet() {
1838[warn] Map<Path, ChangeSetBuilder> returnBuilders;
1839[warn] synchronized (lock) {
1840[warn] returnBuilders = changeBuilders;
1841[warn] changeBuilders = new HashMap<>();
1842[warn] }
1843[warn] return returnBuilders.entrySet().stream()
1844[warn] .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().toChangeSet()));
1845[warn] }
1846[warn] }
1847[warn] /build/repo/core/src/main/java/io/methvin/watcher/changeset/ChangeSetListener.java:48:1: no comment
1848[warn] public Map<Path, ChangeSet> getChangeSet() {
1849[warn] Map<Path, ChangeSetBuilder> returnBuilders;
1850[warn] synchronized (lock) {
1851[warn] returnBuilders = changeBuilders;
1852[warn] changeBuilders = new HashMap<>();
1853[warn] }
1854[warn] return returnBuilders.entrySet().stream()
1855[warn] .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().toChangeSet()));
1856[warn] }
1857[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeListener.java:58:1: no comment
1858[warn] void onEvent(DirectoryChangeEvent event) throws IOException;
1859[warn] /build/repo/core/src/main/java/io/methvin/watcher/visitor/DefaultFileTreeVisitor.java:10:1: no comment
1860[warn] public class DefaultFileTreeVisitor implements FileTreeVisitor {
1861[warn] @Override
1862[warn] public void recursiveVisitFiles(Path file, Callback onDirectory, Callback onFile)
1863[warn] throws IOException {
1864[warn] SimpleFileVisitor<Path> visitor =
1865[warn] new SimpleFileVisitor<Path>() {
1866[warn] @Override
1867[warn] public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
1868[warn] throws IOException {
1869[warn] onDirectory.call(dir);
1870[warn] return FileVisitResult.CONTINUE;
1871[warn] }
1872[warn]
1873[warn] @Override
1874[warn] public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
1875[warn] throws IOException {
1876[warn] onFile.call(file);
1877[warn] return FileVisitResult.CONTINUE;
1878[warn] }
1879[warn]
1880[warn] @Override
1881[warn] public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
1882[warn] onFailure(file, exc);
1883[warn] return FileVisitResult.CONTINUE;
1884[warn] }
1885[warn]
1886[warn] @Override
1887[warn] public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
1888[warn] if (exc != null) onFailure(dir, exc);
1889[warn] return FileVisitResult.CONTINUE;
1890[warn] }
1891[warn] };
1892[warn] Files.walkFileTree(file, visitor);
1893[warn] }
1894[warn]
1895[warn] // To be overridden if needed
1896[warn] protected void onFailure(Path path, IOException exception) throws IOException {}
1897[warn] }
1898[warn] /build/repo/core/src/main/java/io/methvin/watcher/visitor/DefaultFileTreeVisitor.java:46:1: no comment
1899[warn] protected void onFailure(Path path, IOException exception) throws IOException {}
1900[warn] /build/repo/core/src/main/java/io/methvin/watcher/visitor/FileTreeVisitor.java:16:1: no comment
1901[warn] void recursiveVisitFiles(Path file, Callback onDirectory, Callback onFile) throws IOException;
1902[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:22:1: no comment
1903[warn] public final class DirectoryChangeEvent {
1904[warn] public enum EventType {
1905[warn]
1906[warn] /* A new file was created */
1907[warn] CREATE(StandardWatchEventKinds.ENTRY_CREATE),
1908[warn]
1909[warn] /* An existing file was modified */
1910[warn] MODIFY(StandardWatchEventKinds.ENTRY_MODIFY),
1911[warn]
1912[warn] /* A file was deleted */
1913[warn] DELETE(StandardWatchEventKinds.ENTRY_DELETE),
1914[warn]
1915[warn] /* An overflow occurred; some events were lost */
1916[warn] OVERFLOW(StandardWatchEventKinds.OVERFLOW);
1917[warn]
1918[warn] private WatchEvent.Kind<?> kind;
1919[warn]
1920[warn] EventType(WatchEvent.Kind<?> kind) {
1921[warn] this.kind = kind;
1922[warn] }
1923[warn]
1924[warn] public WatchEvent.Kind<?> getWatchEventKind() {
1925[warn] return kind;
1926[warn] }
1927[warn] }
1928[warn]
1929[warn] private final EventType eventType;
1930[warn] private final boolean isDirectory;
1931[warn] private final Path path;
1932[warn] private final FileHash hash;
1933[warn] private final int count;
1934[warn] private final Path rootPath;
1935[warn]
1936[warn] public DirectoryChangeEvent(
1937[warn] EventType eventType,
1938[warn] boolean isDirectory,
1939[warn] Path path,
1940[warn] FileHash hash,
1941[warn] int count,
1942[warn] Path rootPath) {
1943[warn] this.eventType = eventType;
1944[warn] this.isDirectory = isDirectory;
1945[warn] this.hash = hash;
1946[warn] this.path = path;
1947[warn] this.count = count;
1948[warn] this.rootPath = rootPath;
1949[warn] }
1950[warn]
1951[warn] public EventType eventType() {
1952[warn] return eventType;
1953[warn] }
1954[warn]
1955[warn] public Path path() {
1956[warn] return path;
1957[warn] }
1958[warn]
1959[warn] public int count() {
1960[warn] return count;
1961[warn] }
1962[warn]
1963[warn] public Path rootPath() {
1964[warn] return rootPath;
1965[warn] }
1966[warn]
1967[warn] public boolean isDirectory() {
1968[warn] return isDirectory;
1969[warn] }
1970[warn]
1971[warn] public FileHash hash() {
1972[warn] return hash;
1973[warn] }
1974[warn]
1975[warn] @Override
1976[warn] public boolean equals(Object o) {
1977[warn] if (this == o) {
1978[warn] return true;
1979[warn] }
1980[warn] if (o == null || getClass() != o.getClass()) {
1981[warn] return false;
1982[warn] }
1983[warn]
1984[warn] DirectoryChangeEvent that = (DirectoryChangeEvent) o;
1985[warn]
1986[warn] return count == that.count
1987[warn] && eventType == that.eventType
1988[warn] && isDirectory == that.isDirectory
1989[warn] && Objects.equals(path, that.path)
1990[warn] && Objects.equals(rootPath, that.rootPath)
1991[warn] && Objects.equals(hash, that.hash);
1992[warn] }
1993[warn]
1994[warn] @Override
1995[warn] public int hashCode() {
1996[warn] return Objects.hash(eventType, isDirectory, path, count, rootPath, hash);
1997[warn] }
1998[warn]
1999[warn] @Override
2000[warn] public String toString() {
2001[warn] return "DirectoryChangeEvent{"
2002[warn] + "eventType="
2003[warn] + eventType
2004[warn] + ", isDirectory="
2005[warn] + isDirectory
2006[warn] + ", path="
2007[warn] + path
2008[warn] + ", count="
2009[warn] + count
2010[warn] + ", rootPath="
2011[warn] + rootPath
2012[warn] + ", hash="
2013[warn] + ((hash == null) ? "(null)" : hash) // don't want the printout to be too long
2014[warn] + '}';
2015[warn] }
2016[warn] }
2017[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:23:1: no comment
2018[warn] public enum EventType {
2019[warn]
2020[warn] /* A new file was created */
2021[warn] CREATE(StandardWatchEventKinds.ENTRY_CREATE),
2022[warn]
2023[warn] /* An existing file was modified */
2024[warn] MODIFY(StandardWatchEventKinds.ENTRY_MODIFY),
2025[warn]
2026[warn] /* A file was deleted */
2027[warn] DELETE(StandardWatchEventKinds.ENTRY_DELETE),
2028[warn]
2029[warn] /* An overflow occurred; some events were lost */
2030[warn] OVERFLOW(StandardWatchEventKinds.OVERFLOW);
2031[warn]
2032[warn] private WatchEvent.Kind<?> kind;
2033[warn]
2034[warn] EventType(WatchEvent.Kind<?> kind) {
2035[warn] this.kind = kind;
2036[warn] }
2037[warn]
2038[warn] public WatchEvent.Kind<?> getWatchEventKind() {
2039[warn] return kind;
2040[warn] }
2041[warn] }
2042[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:55:1: no comment
2043[warn] public DirectoryChangeEvent(
2044[warn] EventType eventType,
2045[warn] boolean isDirectory,
2046[warn] Path path,
2047[warn] FileHash hash,
2048[warn] int count,
2049[warn] Path rootPath) {
2050[warn] this.eventType = eventType;
2051[warn] this.isDirectory = isDirectory;
2052[warn] this.hash = hash;
2053[warn] this.path = path;
2054[warn] this.count = count;
2055[warn] this.rootPath = rootPath;
2056[warn] }
2057[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:78:1: no comment
2058[warn] public int count() {
2059[warn] return count;
2060[warn] }
2061[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:70:1: no comment
2062[warn] public EventType eventType() {
2063[warn] return eventType;
2064[warn] }
2065[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:90:1: no comment
2066[warn] public FileHash hash() {
2067[warn] return hash;
2068[warn] }
2069[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:86:1: no comment
2070[warn] public boolean isDirectory() {
2071[warn] return isDirectory;
2072[warn] }
2073[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:74:1: no comment
2074[warn] public Path path() {
2075[warn] return path;
2076[warn] }
2077[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:82:1: no comment
2078[warn] public Path rootPath() {
2079[warn] return rootPath;
2080[warn] }
2081[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:43:1: no comment
2082[warn] public WatchEvent.Kind<?> getWatchEventKind() {
2083[warn] return kind;
2084[warn] }
2085[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:26:1: no comment
2086[warn] CREATE(StandardWatchEventKinds.ENTRY_CREATE)
2087[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:32:1: no comment
2088[warn] DELETE(StandardWatchEventKinds.ENTRY_DELETE)
2089[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:29:1: no comment
2090[warn] MODIFY(StandardWatchEventKinds.ENTRY_MODIFY)
2091[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeEvent.java:35:1: no comment
2092[warn] OVERFLOW(StandardWatchEventKinds.OVERFLOW)
2093[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeListener.java:24:1: no comment
2094[warn] static DirectoryChangeListener of(DirectoryChangeListener... listeners) {
2095[warn] return new DirectoryChangeListener() {
2096[warn] @Override
2097[warn] public void onEvent(DirectoryChangeEvent event) throws IOException {
2098[warn] for (DirectoryChangeListener listener : listeners) {
2099[warn] listener.onEvent(event);
2100[warn] }
2101[warn] }
2102[warn]
2103[warn] @Override
2104[warn] public void onException(Exception e) {
2105[warn] for (DirectoryChangeListener listener : listeners) {
2106[warn] listener.onException(e);
2107[warn] }
2108[warn] }
2109[warn]
2110[warn] @Override
2111[warn] public void onIdle(int count) {
2112[warn] for (DirectoryChangeListener listener : listeners) {
2113[warn] listener.onIdle(count);
2114[warn] }
2115[warn] }
2116[warn]
2117[warn] @Override
2118[warn] public boolean isWatching() {
2119[warn] boolean anyWatching = false;
2120[warn] for (DirectoryChangeListener listener : listeners) {
2121[warn] anyWatching |= listener.isWatching();
2122[warn] }
2123[warn] return anyWatching;
2124[warn] }
2125[warn] };
2126[warn] }
2127[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryChangeListener.java:65:1: no comment
2128[warn] default void onIdle(int count) {
2129[warn] // ignore onIdle by default
2130[warn] }
2131[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:172:1: no @return
2132[warn] public static Builder builder() {
2133[warn] return new Builder();
2134[warn] }
2135[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:214:1: no @return
2136[warn] public CompletableFuture<Void> watchAsync() {
2137[warn] return watchAsync(ForkJoinPool.commonPool());
2138[warn] }
2139[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:227:1: no @return
2140[warn] public CompletableFuture<Void> watchAsync(Executor executor) {
2141[warn] try {
2142[warn] registerPaths();
2143[warn] return CompletableFuture.supplyAsync(
2144[warn] () -> {
2145[warn] runEventLoop();
2146[warn] return null;
2147[warn] },
2148[warn] executor);
2149[warn] } catch (Throwable t) {
2150[warn] CompletableFuture<Void> f = new CompletableFuture<>();
2151[warn] f.completeExceptionally(t);
2152[warn] return f;
2153[warn] }
2154[warn] }
2155[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:46:1: no comment
2156[warn] public class DirectoryWatcher {
2157[warn]
2158[warn] /**
2159[warn] * A builder for a {@link DirectoryWatcher}. Use {@code DirectoryWatcher.builder()} to get a new
2160[warn] * instance.
2161[warn] */
2162[warn] public static final class Builder {
2163[warn] private List<Path> paths = Collections.emptyList();
2164[warn] private DirectoryChangeListener listener = (event -> {});
2165[warn] private Logger logger = null;
2166[warn] private FileHasher fileHasher = FileHasher.DEFAULT_FILE_HASHER;
2167[warn] private WatchService watchService = null;
2168[warn] private FileTreeVisitor fileTreeVisitor = null;
2169[warn]
2170[warn] private Builder() {}
2171[warn]
2172[warn] /** Set multiple paths to watch. */
2173[warn] public Builder paths(List<Path> paths) {
2174[warn] this.paths = paths;
2175[warn] return this;
2176[warn] }
2177[warn]
2178[warn] /** Set a single path to watch. */
2179[warn] public Builder path(Path path) {
2180[warn] return paths(Collections.singletonList(path));
2181[warn] }
2182[warn]
2183[warn] /** Set a listener that will be called when a directory change event occurs. */
2184[warn] public Builder listener(DirectoryChangeListener listener) {
2185[warn] this.listener = listener;
2186[warn] return this;
2187[warn] }
2188[warn]
2189[warn] /**
2190[warn] * Set a {@link WatchService} implementation that will be used by the watcher.
2191[warn] *
2192[warn] * <p>By default, this detects your OS and either uses the native JVM watcher or the macOS
2193[warn] * watcher.
2194[warn] */
2195[warn] public Builder watchService(WatchService watchService) {
2196[warn] this.watchService = watchService;
2197[warn] return this;
2198[warn] }
2199[warn]
2200[warn] /**
2201[warn] * Set a logger to be used by the watcher. This defaults to {@code
2202[warn] * LoggerFactory.getLogger(DirectoryWatcher.class)}
2203[warn] */
2204[warn] public Builder logger(Logger logger) {
2205[warn] this.logger = logger;
2206[warn] return this;
2207[warn] }
2208[warn]
2209[warn] /**
2210[warn] * Defines whether file hashing should be used to catch duplicate events. Defaults to {@code
2211[warn] * true}.
2212[warn] */
2213[warn] public Builder fileHashing(boolean enabled) {
2214[warn] this.fileHasher = enabled ? FileHasher.DEFAULT_FILE_HASHER : null;
2215[warn] return this;
2216[warn] }
2217[warn]
2218[warn] /**
2219[warn] * Defines the file hasher to be used by the watcher.
2220[warn] *
2221[warn] * <p>Note: will implicitly enable file hashing. Setting to null is equivalent to {@code
2222[warn] * fileHashing(false)}
2223[warn] */
2224[warn] public Builder fileHasher(FileHasher fileHasher) {
2225[warn] this.fileHasher = fileHasher;
2226[warn] return this;
2227[warn] }
2228[warn]
2229[warn] /** Defines the file tree visitor to be used by the watcher. */
2230[warn] public Builder fileTreeVisitor(FileTreeVisitor fileTreeVisitor) {
2231[warn] this.fileTreeVisitor = fileTreeVisitor;
2232[warn] return this;
2233[warn] }
2234[warn]
2235[warn] public DirectoryWatcher build() throws IOException {
2236[warn] if (fileTreeVisitor == null) {
2237[warn] fileTreeVisitor = FileTreeVisitor.DEFAULT_FILE_TREE_VISITOR;
2238[warn] }
2239[warn] if (watchService == null) {
2240[warn] osDefaultWatchService(fileTreeVisitor);
2241[warn] }
2242[warn] if (logger == null) {
2243[warn] staticLogger();
2244[warn] }
2245[warn] return new DirectoryWatcher(
2246[warn] paths, listener, watchService, fileHasher, fileTreeVisitor, logger);
2247[warn] }
2248[warn]
2249[warn] private Builder osDefaultWatchService(FileTreeVisitor fileTreeVisitor) throws IOException {
2250[warn] boolean isMac = System.getProperty("os.name").toLowerCase().contains("mac");
2251[warn] if (isMac) {
2252[warn] return watchService(
2253[warn] new MacOSXListeningWatchService(
2254[warn] new MacOSXListeningWatchService.Config() {
2255[warn] @Override
2256[warn] public FileHasher fileHasher() {
2257[warn] /**
2258[warn] * Always return null here. When MacOSXListeningWatchService is used with
2259[warn] * DirectoryWatcher, then the hashing should happen within DirectoryWatcher. If
2260[warn] * users wish to override this then they must instantiate
2261[warn] * MacOSXListeningWatchService and pass it to DirectoryWatcher.
2262[warn] */
2263[warn] return null;
2264[warn] }
2265[warn]
2266[warn] @Override
2267[warn] public FileTreeVisitor fileTreeVisitor() {
2268[warn] return fileTreeVisitor;
2269[warn] }
2270[warn] }));
2271[warn] } else {
2272[warn] return watchService(FileSystems.getDefault().newWatchService());
2273[warn] }
2274[warn] }
2275[warn]
2276[warn] private Builder staticLogger() {
2277[warn] return logger(LoggerFactory.getLogger(DirectoryWatcher.class));
2278[warn] }
2279[warn] }
2280[warn]
2281[warn] /** Get a new builder for a {@link DirectoryWatcher}. */
2282[warn] public static Builder builder() {
2283[warn] return new Builder();
2284[warn] }
2285[warn]
2286[warn] private final Logger logger;
2287[warn] private final WatchService watchService;
2288[warn] private final List<Path> paths;
2289[warn] private final boolean isMac;
2290[warn] private final DirectoryChangeListener listener;
2291[warn] private final FileHasher fileHasher;
2292[warn] private final FileTreeVisitor fileTreeVisitor;
2293[warn]
2294[warn] private final Map<Path, Path> registeredPathToRootPath = new HashMap<>();;
2295[warn] private final SortedMap<Path, FileHash> pathHashes = new ConcurrentSkipListMap<>();
2296[warn] private final Set<Path> directories =
2297[warn] Collections.newSetFromMap(new ConcurrentHashMap<Path, Boolean>());
2298[warn] private final Map<WatchKey, Path> keyRoots = new ConcurrentHashMap<>();
2299[warn]
2300[warn] private volatile boolean closed = false;
2301[warn]
2302[warn] // set to null until we check if FILE_TREE is supported
2303[warn] private Boolean fileTreeSupported = null;
2304[warn]
2305[warn] public DirectoryWatcher(
2306[warn] List<Path> paths,
2307[warn] DirectoryChangeListener listener,
2308[warn] WatchService watchService,
2309[warn] FileHasher fileHasher,
2310[warn] FileTreeVisitor fileTreeVisitor,
2311[warn] Logger logger) {
2312[warn] this.paths = paths.stream().map(p -> p.toAbsolutePath()).collect(Collectors.toList());
2313[warn] this.listener = listener;
2314[warn] this.watchService = watchService;
2315[warn] this.isMac = watchService instanceof MacOSXListeningWatchService;
2316[warn] this.fileHasher = fileHasher;
2317[warn] this.fileTreeVisitor = fileTreeVisitor;
2318[warn] this.logger = logger;
2319[warn] }
2320[warn]
2321[warn] /**
2322[warn] * Asynchronously watch the directories using {@code ForkJoinPool.commonPool()} as the executor
2323[warn] */
2324[warn] public CompletableFuture<Void> watchAsync() {
2325[warn] return watchAsync(ForkJoinPool.commonPool());
2326[warn] }
2327[warn]
2328[warn] /**
2329[warn] * Start watching for changes asynchronously.
2330[warn] *
2331[warn] * <p>The future completes when the listener stops listening or the watcher is closed.
2332[warn] *
2333[warn] * <p>This method will block until the watcher is initialized and successfully watching.
2334[warn] *
2335[warn] * @param executor the executor to use to watch asynchronously
2336[warn] */
2337[warn] public CompletableFuture<Void> watchAsync(Executor executor) {
2338[warn] try {
2339[warn] registerPaths();
2340[warn] return CompletableFuture.supplyAsync(
2341[warn] () -> {
2342[warn] runEventLoop();
2343[warn] return null;
2344[warn] },
2345[warn] executor);
2346[warn] } catch (Throwable t) {
2347[warn] CompletableFuture<Void> f = new CompletableFuture<>();
2348[warn] f.completeExceptionally(t);
2349[warn] return f;
2350[warn] }
2351[warn] }
2352[warn]
2353[warn] /**
2354[warn] * Watch for changes; block until the listener stops listening or the watcher is closed.
2355[warn] *
2356[warn] * @throws IllegalStateException if the directory watcher is closed when watch() is called.
2357[warn] */
2358[warn] public void watch() {
2359[warn] registerPaths();
2360[warn] runEventLoop();
2361[warn] }
2362[warn]
2363[warn] public Map<Path, FileHash> pathHashes() {
2364[warn] return Collections.unmodifiableMap(pathHashes);
2365[warn] }
2366[warn]
2367[warn] public DirectoryChangeListener getListener() {
2368[warn] return listener;
2369[warn] }
2370[warn]
2371[warn] public void close() throws IOException {
2372[warn] watchService.close();
2373[warn] closed = true;
2374[warn] }
2375[warn]
2376[warn] public boolean isClosed() {
2377[warn] return closed;
2378[warn] }
2379[warn]
2380[warn] private boolean isFileTreeSupported() {
2381[warn] if (fileTreeSupported == null) {
2382[warn] throw new IllegalStateException("fileTreeSupported not initialized");
2383[warn] }
2384[warn] return fileTreeSupported;
2385[warn] }
2386[warn]
2387[warn] private void registerPaths() {
2388[warn] try {
2389[warn] PathUtils.initWatcherState(paths, fileHasher, fileTreeVisitor, pathHashes, directories);
2390[warn]
2391[warn] for (Path path : paths) {
2392[warn] registerAll(path, path);
2393[warn] }
2394[warn] } catch (IOException e) {
2395[warn] throw new UncheckedIOException(e);
2396[warn] }
2397[warn] }
2398[warn]
2399[warn] private void runEventLoop() {
2400[warn] if (closed) {
2401[warn] throw new IllegalStateException("watcher already closed");
2402[warn] }
2403[warn] int eventCount = 0;
2404[warn] while (listener.isWatching()) {
2405[warn] // wait for key to be signalled
2406[warn] WatchKey key;
2407[warn] try {
2408[warn] key = watchService.poll();
2409[warn] if (key == null) {
2410[warn] listener.onIdle(eventCount);
2411[warn] key = watchService.take();
2412[warn] }
2413[warn] } catch (InterruptedException | ClosedWatchServiceException e) {
2414[warn] return;
2415[warn] }
2416[warn] for (WatchEvent<?> event : key.pollEvents()) {
2417[warn] eventCount++;
2418[warn] try {
2419[warn] WatchEvent.Kind<?> kind = event.kind();
2420[warn] // Context for directory entry event is the file name of entry
2421[warn] WatchEvent<Path> ev = PathUtils.cast(event);
2422[warn] int count = ev.count();
2423[warn] Path eventPath = ev.context();
2424[warn] if (!keyRoots.containsKey(key)) {
2425[warn] throw new IllegalStateException(
2426[warn] "WatchService returned key [" + key + "] but it was not found in keyRoots!");
2427[warn] }
2428[warn] Path registeredPath = keyRoots.get(key);
2429[warn] Path rootPath = registeredPathToRootPath.get(registeredPath);
2430[warn] Path childPath = eventPath == null ? null : keyRoots.get(key).resolve(eventPath);
2431[warn] logger.debug("{} [{}]", kind, childPath);
2432[warn] /*
2433[warn] * If a directory is created, and we're watching recursively, then register it
2434[warn] * and its sub-directories.
2435[warn] */
2436[warn] if (kind == OVERFLOW) {
2437[warn] onEvent(EventType.OVERFLOW, false, childPath, count, rootPath);
2438[warn] } else if (eventPath == null) {
2439[warn] throw new IllegalStateException("WatchService returned a null path for " + kind.name());
2440[warn] } else if (kind == ENTRY_CREATE) {
2441[warn] boolean isDirectory = Files.isDirectory(childPath, NOFOLLOW_LINKS);
2442[warn] if (isDirectory) {
2443[warn] if (!isFileTreeSupported()) {
2444[warn] registerAll(childPath, rootPath);
2445[warn] }
2446[warn] /*
2447[warn] * Our custom Mac service sends subdirectory changes but the Windows/Linux do
2448[warn] * not. Walk the file tree to make sure we send create events for any files that
2449[warn] * were created.
2450[warn] */
2451[warn] if (!isMac) {
2452[warn] fileTreeVisitor.recursiveVisitFiles(
2453[warn] childPath,
2454[warn] dir -> notifyCreateEvent(true, dir, count, rootPath),
2455[warn] file -> notifyCreateEvent(false, file, count, rootPath));
2456[warn] } else {
2457[warn] notifyCreateEvent(true, childPath, count, rootPath);
2458[warn] }
2459[warn] } else {
2460[warn] notifyCreateEvent(false, childPath, count, rootPath);
2461[warn] }
2462[warn] } else if (kind == ENTRY_MODIFY) {
2463[warn] boolean isDirectory = directories.contains(childPath);
2464[warn]
2465[warn] if (fileHasher == null) {
2466[warn] onEvent(EventType.MODIFY, isDirectory, childPath, count, rootPath);
2467[warn] } else {
2468[warn] /*
2469[warn] * Note that existingHash may be null due to the file being created before we
2470[warn] * start listening It's important we don't discard the event in this case
2471[warn] */
2472[warn] FileHash existingHash = pathHashes.get(childPath);
2473[warn]
2474[warn] /*
2475[warn] * newHash can be null when using File#delete() on windows - it generates MODIFY
2476[warn] * and DELETE in succession. In this case the MODIFY event can be safely ignored
2477[warn] */
2478[warn] FileHash newHash = PathUtils.hash(fileHasher, childPath);
2479[warn]
2480[warn] if (newHash != null && !newHash.equals(existingHash)) {
2481[warn] pathHashes.put(childPath, newHash);
2482[warn] onEvent(EventType.MODIFY, isDirectory, childPath, count, rootPath);
2483[warn] } else if (newHash == null) {
2484[warn] logger.debug(
2485[warn] "Failed to hash modified file [{}]. It may have been deleted.", childPath);
2486[warn] }
2487[warn] }
2488[warn] } else if (kind == ENTRY_DELETE) {
2489[warn] if (fileHasher == null) {
2490[warn] boolean isDirectory = directories.remove(childPath);
2491[warn] // hashing is disabled, so just notify on the path we got the event for
2492[warn] onEvent(EventType.DELETE, isDirectory, childPath, count, rootPath);
2493[warn] } else {
2494[warn] // hashing is enabled, so delete the hashes
2495[warn] for (Path path : PathUtils.subtreePaths(pathHashes, childPath)) {
2496[warn] boolean isDirectory = directories.remove(path);
2497[warn] pathHashes.remove(path);
2498[warn] onEvent(EventType.DELETE, isDirectory, path, count, rootPath);
2499[warn] }
2500[warn] }
2501[warn] }
2502[warn] } catch (Exception e) {
2503[warn] logger.debug("DirectoryWatcher got an exception while watching!", e);
2504[warn] listener.onException(e);
2505[warn] }
2506[warn] }
2507[warn] boolean valid = key.reset();
2508[warn] if (!valid) {
2509[warn] logger.debug("WatchKey for [{}] no longer valid; removing.", key.watchable());
2510[warn] // remove the key from the keyRoots
2511[warn] Path registeredPath = keyRoots.remove(key);
2512[warn]
2513[warn] // Also remove from the registeredPathToRootPath maps
2514[warn] registeredPathToRootPath.remove(registeredPath);
2515[warn]
2516[warn] // if there are no more keys left to watch, we can break out
2517[warn] if (keyRoots.isEmpty()) {
2518[warn] logger.debug("No more directories left to watch; terminating watcher.");
2519[warn] break;
2520[warn] }
2521[warn] }
2522[warn] }
2523[warn] try {
2524[warn] close();
2525[warn] } catch (IOException e) {
2526[warn] throw new UncheckedIOException(e);
2527[warn] }
2528[warn] }
2529[warn]
2530[warn] private void onEvent(
2531[warn] EventType eventType, boolean isDirectory, Path childPath, int count, Path rootPath)
2532[warn] throws IOException {
2533[warn] logger.debug("-> {} [{}] (isDirectory: {})", eventType, childPath, isDirectory);
2534[warn] FileHash hash = pathHashes.get(childPath);
2535[warn] listener.onEvent(
2536[warn] new DirectoryChangeEvent(eventType, isDirectory, childPath, hash, count, rootPath));
2537[warn] }
2538[warn]
2539[warn] private void registerAll(final Path start, final Path context) throws IOException {
2540[warn] if (!Boolean.FALSE.equals(fileTreeSupported)) {
2541[warn] // Try using FILE_TREE modifier since we aren't certain that it's unsupported
2542[warn] try {
2543[warn] register(start, true, context);
2544[warn] // Assume FILE_TREE is supported
2545[warn] fileTreeSupported = true;
2546[warn] } catch (UnsupportedOperationException e) {
2547[warn] // UnsupportedOperationException should only happen if FILE_TREE is unsupported
2548[warn] logger.debug("Assuming ExtendedWatchEventModifier.FILE_TREE is not supported", e);
2549[warn] fileTreeSupported = false;
2550[warn] // If we failed to use the FILE_TREE modifier, try again without
2551[warn] registerAll(start, context);
2552[warn] }
2553[warn] } else {
2554[warn] // Since FILE_TREE is unsupported, register root directory and sub-directories
2555[warn] fileTreeVisitor.recursiveVisitFiles(start, dir -> register(dir, false, context), file -> {});
2556[warn] }
2557[warn] }
2558[warn]
2559[warn] // Internal method to be used by registerAll
2560[warn] private void register(Path directory, boolean useFileTreeModifier, Path context)
2561[warn] throws IOException {
2562[warn] logger.debug("Registering [{}].", directory);
2563[warn] Watchable watchable = isMac ? new WatchablePath(directory) : directory;
2564[warn] WatchEvent.Modifier[] modifiers =
2565[warn] useFileTreeModifier
2566[warn] ? new WatchEvent.Modifier[] {ExtendedWatchEventModifier.FILE_TREE}
2567[warn] : new WatchEvent.Modifier[] {};
2568[warn] WatchEvent.Kind<?>[] kinds =
2569[warn] new WatchEvent.Kind<?>[] {ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY};
2570[warn] WatchKey watchKey = watchable.register(watchService, kinds, modifiers);
2571[warn] keyRoots.put(watchKey, directory);
2572[warn] registeredPathToRootPath.put(directory, context);
2573[warn] }
2574[warn]
2575[warn] private void notifyCreateEvent(boolean isDirectory, Path path, int count, Path rootPath)
2576[warn] throws IOException {
2577[warn] if (fileHasher != null) {
2578[warn] FileHash newHash = PathUtils.hash(fileHasher, path);
2579[warn] if (newHash == null) {
2580[warn] // Hashing could fail for locked files on Windows.
2581[warn] // Skip notification only if we confirm the file does not exist.
2582[warn] if (Files.notExists(path)) {
2583[warn] logger.debug("Failed to hash created file [{}]. It may have been deleted.", path);
2584[warn] // Skip notifying the event.
2585[warn] return;
2586[warn] } else {
2587[warn] // Just warn here and continue to notify the event.
2588[warn] logger.debug("Failed to hash created file [{}]. It may be locked.", path);
2589[warn] }
2590[warn] } else {
2591[warn] FileHash oldHash = pathHashes.put(path, newHash);
2592[warn] if (oldHash != null) {
2593[warn] if (oldHash == newHash) {
2594[warn] // Creates might occur just before we traverse and notify for files in a new directory.
2595[warn] // We generally want to skip the duplicate if the hash has not changed.
2596[warn] logger.debug("Skipping duplicate create event for file [{}].", path);
2597[warn] return;
2598[warn] } else {
2599[warn] // This might happen if events were discarded and perhaps we missed a DELETE event.
2600[warn] logger.debug("Sending MODIFY instead of CREATE for existing hashed file [{}].", path);
2601[warn] onEvent(EventType.MODIFY, isDirectory, path, count, rootPath);
2602[warn] return;
2603[warn] }
2604[warn] }
2605[warn] }
2606[warn] }
2607[warn] if (isDirectory) {
2608[warn] directories.add(path);
2609[warn] }
2610[warn] onEvent(EventType.CREATE, isDirectory, path, count, rootPath);
2611[warn] }
2612[warn] }
2613[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:195:1: no comment
2614[warn] public DirectoryWatcher(
2615[warn] List<Path> paths,
2616[warn] DirectoryChangeListener listener,
2617[warn] WatchService watchService,
2618[warn] FileHasher fileHasher,
2619[warn] FileTreeVisitor fileTreeVisitor,
2620[warn] Logger logger) {
2621[warn] this.paths = paths.stream().map(p -> p.toAbsolutePath()).collect(Collectors.toList());
2622[warn] this.listener = listener;
2623[warn] this.watchService = watchService;
2624[warn] this.isMac = watchService instanceof MacOSXListeningWatchService;
2625[warn] this.fileHasher = fileHasher;
2626[warn] this.fileTreeVisitor = fileTreeVisitor;
2627[warn] this.logger = logger;
2628[warn] }
2629[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:261:1: no comment
2630[warn] public void close() throws IOException {
2631[warn] watchService.close();
2632[warn] closed = true;
2633[warn] }
2634[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:257:1: no comment
2635[warn] public DirectoryChangeListener getListener() {
2636[warn] return listener;
2637[warn] }
2638[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:266:1: no comment
2639[warn] public boolean isClosed() {
2640[warn] return closed;
2641[warn] }
2642[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:253:1: no comment
2643[warn] public Map<Path, FileHash> pathHashes() {
2644[warn] return Collections.unmodifiableMap(pathHashes);
2645[warn] }
2646[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:63:1: no @param for paths
2647[warn] public Builder paths(List<Path> paths) {
2648[warn] this.paths = paths;
2649[warn] return this;
2650[warn] }
2651[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:69:1: no @param for path
2652[warn] public Builder path(Path path) {
2653[warn] return paths(Collections.singletonList(path));
2654[warn] }
2655[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:74:1: no @param for listener
2656[warn] public Builder listener(DirectoryChangeListener listener) {
2657[warn] this.listener = listener;
2658[warn] return this;
2659[warn] }
2660[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:85:1: no @param for watchService
2661[warn] public Builder watchService(WatchService watchService) {
2662[warn] this.watchService = watchService;
2663[warn] return this;
2664[warn] }
2665[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:94:1: no @param for logger
2666[warn] public Builder logger(Logger logger) {
2667[warn] this.logger = logger;
2668[warn] return this;
2669[warn] }
2670[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:103:1: no @param for enabled
2671[warn] public Builder fileHashing(boolean enabled) {
2672[warn] this.fileHasher = enabled ? FileHasher.DEFAULT_FILE_HASHER : null;
2673[warn] return this;
2674[warn] }
2675[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:114:1: no @param for fileHasher
2676[warn] public Builder fileHasher(FileHasher fileHasher) {
2677[warn] this.fileHasher = fileHasher;
2678[warn] return this;
2679[warn] }
2680[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:120:1: no @param for fileTreeVisitor
2681[warn] public Builder fileTreeVisitor(FileTreeVisitor fileTreeVisitor) {
2682[warn] this.fileTreeVisitor = fileTreeVisitor;
2683[warn] return this;
2684[warn] }
2685[warn] /build/repo/core/src/main/java/io/methvin/watcher/DirectoryWatcher.java:125:1: no comment
2686[warn] public DirectoryWatcher build() throws IOException {
2687[warn] if (fileTreeVisitor == null) {
2688[warn] fileTreeVisitor = FileTreeVisitor.DEFAULT_FILE_TREE_VISITOR;
2689[warn] }
2690[warn] if (watchService == null) {
2691[warn] osDefaultWatchService(fileTreeVisitor);
2692[warn] }
2693[warn] if (logger == null) {
2694[warn] staticLogger();
2695[warn] }
2696[warn] return new DirectoryWatcher(
2697[warn] paths, listener, watchService, fileHasher, fileTreeVisitor, logger);
2698[warn] }
2699[warn] /build/repo/core/src/main/java/io/methvin/watcher/hashing/FileHash.java:40:1: no comment
2700[warn] public static FileHash directory() {
2701[warn] return DIRECTORY;
2702[warn] }
2703[warn] /build/repo/core/src/main/java/io/methvin/watcher/hashing/FileHash.java:30:1: no comment
2704[warn] public static FileHash fromBytes(byte[] value) {
2705[warn] return new ByteArrayFileHash(Arrays.copyOf(value, value.length));
2706[warn] }
2707[warn] /build/repo/core/src/main/java/io/methvin/watcher/hashing/FileHash.java:34:1: no comment
2708[warn] public static FileHash fromLong(long value) {
2709[warn] ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
2710[warn] buffer.putLong(value);
2711[warn] return new ByteArrayFileHash(buffer.array());
2712[warn] }
2713[warn] /build/repo/core/src/main/java/io/methvin/watcher/hashing/FileHasher.java:63:1: no comment
2714[warn] FileHash hash(Path path) throws IOException;
2715[warn] /build/repo/core/src/main/java/io/methvin/watcher/visitor/FileTreeVisitor.java:7:1: no comment
2716[warn] public interface FileTreeVisitor {
2717[warn]
2718[warn] /** The default file tree visitor instance, which uses Files.walkFileTree. */
2719[warn] FileTreeVisitor DEFAULT_FILE_TREE_VISITOR = new DefaultFileTreeVisitor();
2720[warn]
2721[warn] interface Callback {
2722[warn] void call(Path p) throws IOException;
2723[warn] }
2724[warn]
2725[warn] void recursiveVisitFiles(Path file, Callback onDirectory, Callback onFile) throws IOException;
2726[warn] }
2727[warn] /build/repo/core/src/main/java/io/methvin/watcher/visitor/FileTreeVisitor.java:12:1: no comment
2728[warn] interface Callback {
2729[warn] void call(Path p) throws IOException;
2730[warn] }
2731[warn] /build/repo/core/src/main/java/io/methvin/watcher/visitor/FileTreeVisitor.java:13:1: no comment
2732[warn] void call(Path p) throws IOException;
2733[warn] /build/repo/core/src/main/java/io/methvin/watchservice/jna/FSEventStreamRef.java:18:1: no comment
2734[warn] public class FSEventStreamRef extends PointerByReference {}
2735[warn] /build/repo/core/src/main/java/io/methvin/watchservice/MacOSXListeningWatchService.java:172:1: no comment
2736[warn] public static class CFRunLoopThread extends Thread {
2737[warn] private final FSEventStreamRef streamRef;
2738[warn] private CFRunLoopRef runLoopRef;
2739[warn] private boolean isClosed = false;
2740[warn]
2741[warn] public CFRunLoopThread(FSEventStreamRef streamRef, File file) {
2742[warn] super("WatchService for " + file);
2743[warn] this.streamRef = streamRef;
2744[warn] }
2745[warn]
2746[warn] @Override
2747[warn] public void run() {
2748[warn] synchronized (streamRef) {
2749[warn] if (isClosed) return;
2750[warn] runLoopRef = CarbonAPI.INSTANCE.CFRunLoopGetCurrent();
2751[warn] final CFStringRef runLoopMode = CFStringRef.toCFString("kCFRunLoopDefaultMode");
2752[warn] CarbonAPI.INSTANCE.FSEventStreamScheduleWithRunLoop(streamRef, runLoopRef, runLoopMode);
2753[warn] CarbonAPI.INSTANCE.FSEventStreamStart(streamRef);
2754[warn] }
2755[warn] CarbonAPI.INSTANCE.CFRunLoopRun();
2756[warn] }
2757[warn]
2758[warn] public void close() {
2759[warn] synchronized (streamRef) {
2760[warn] if (isClosed) return;
2761[warn] if (runLoopRef != null) {
2762[warn] CarbonAPI.INSTANCE.CFRunLoopStop(runLoopRef);
2763[warn] CarbonAPI.INSTANCE.FSEventStreamStop(streamRef);
2764[warn] CarbonAPI.INSTANCE.FSEventStreamInvalidate(streamRef);
2765[warn] }
2766[warn] CarbonAPI.INSTANCE.FSEventStreamRelease(streamRef);
2767[warn] isClosed = true;
2768[warn] }
2769[warn] }
2770[warn] }
2771[warn] /build/repo/core/src/main/java/io/methvin/watchservice/MacOSXListeningWatchService.java:118:1: no comment
2772[warn] public MacOSXListeningWatchService() {
2773[warn] this(new Config() {});
2774[warn] }
2775[warn] /build/repo/core/src/main/java/io/methvin/watchservice/MacOSXListeningWatchService.java:109:1: no comment
2776[warn] public MacOSXListeningWatchService(Config config) {
2777[warn] this.latency = config.latency();
2778[warn] this.queueSize = config.queueSize();
2779[warn] this.fileTreeVisitor = config.fileTreeVisitor();
2780[warn] FileHasher hasher = config.fileHasher();
2781[warn] this.fileLevelEvents = hasher == null || config.fileLevelEvents();
2782[warn] this.fileHasher = hasher == null ? INCREMENTING_FILE_HASHER : hasher;
2783[warn] }
2784[warn] /build/repo/core/src/main/java/io/methvin/watchservice/AbstractWatchService.java:69:1: no @param for key
2785[warn] public void cancelled(AbstractWatchKey key) {}
2786[warn] /build/repo/core/src/main/java/io/methvin/watchservice/MacOSXListeningWatchService.java:217:1: no comment
2787[warn] public synchronized void close(
2788[warn] CFRunLoopThread runLoopThread, CarbonAPI.FSEventStreamCallback callback, Path path) {
2789[warn] threadList.remove(runLoopThread);
2790[warn] callbackList.remove(callback);
2791[warn] pathsWatching.remove(path);
2792[warn] runLoopThread.close();
2793[warn] }
2794[warn] /build/repo/core/src/main/java/io/methvin/watchservice/AbstractWatchService.java:57:1: no @return
2795[warn] public boolean isOpen() {
2796[warn] return open.get();
2797[warn] }
2798[warn] /build/repo/core/src/main/java/io/methvin/watchservice/AbstractWatchService.java:52:1: no @param for watchable
2799[warn] public abstract AbstractWatchKey register(
2800[warn] WatchablePath watchable, Iterable<? extends WatchEvent.Kind<?>> eventTypes)
2801[warn] throws IOException;
2802[info] 100 warnings
2803[warn] Loading source file DirectoryChangeEvent.java...
2804[warn] Loading source file DirectoryWatcher.java...
2805[warn] Loading source file DirectoryChangeListener.java...
2806[warn] Loading source file PathUtils.java...
2807[warn] Loading source file OnTimeoutListener.java...
2808[warn] Loading source file AbstractWatchKey.java...
2809[warn] Loading source file MacOSXListeningWatchService.java...
2810[warn] Loading source file WatchablePath.java...
2811[warn] Loading source file MacOSXWatchKey.java...
2812[warn] Loading source file AbstractWatchService.java...
2813[warn] Loading source file DefaultFileTreeVisitor.java...
2814[warn] Loading source file FileTreeVisitor.java...
2815[warn] Loading source file ChangeSetImpl.java...
2816[warn] Loading source file ChangeSetEntry.java...
2817[warn] Loading source file ChangeSetBuilder.java...
2818[warn] Loading source file ChangeSetListener.java...
2819[warn] Loading source file ChangeSet.java...
2820[warn] Loading source file ByteArrayFileHash.java...
2821[warn] Loading source file FileHasher.java...
2822[warn] Loading source file Murmur3F.java...
2823[warn] Loading source file FileHash.java...
2824[warn] Loading source file CFIndex.java...
2825[warn] Loading source file FSEventStreamRef.java...
2826[warn] Loading source file CFAllocatorRef.java...
2827[warn] Loading source file CarbonAPI.java...
2828[warn] Loading source file CFArrayRef.java...
2829[warn] Loading source file CFRunLoopRef.java...
2830[warn] Loading source file CFStringRef.java...
2831[warn] Constructing Javadoc information...
2832[warn] Building index for all the packages and classes...
2833[warn] Standard Doclet version 17.0.8+7
2834[warn] Building tree for all the packages and classes...
2835[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/jna/CarbonAPI.html...
2836[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/jna/CarbonAPI.FSEventStreamCallback.html...
2837[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/jna/CFAllocatorRef.html...
2838[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/jna/CFArrayRef.html...
2839[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/jna/CFIndex.html...
2840[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/jna/CFRunLoopRef.html...
2841[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/jna/CFStringRef.html...
2842[warn] Generating /build/repo/core/target/api/io/methvin/watcher/changeset/ChangeSet.html...
2843[warn] Generating /build/repo/core/target/api/io/methvin/watcher/changeset/ChangeSetEntry.html...
2844[warn] Generating /build/repo/core/target/api/io/methvin/watcher/changeset/ChangeSetListener.html...
2845[warn] Generating /build/repo/core/target/api/io/methvin/watcher/visitor/DefaultFileTreeVisitor.html...
2846[warn] Generating /build/repo/core/target/api/io/methvin/watcher/DirectoryChangeEvent.html...
2847[warn] Generating /build/repo/core/target/api/io/methvin/watcher/DirectoryChangeEvent.EventType.html...
2848[warn] Generating /build/repo/core/target/api/io/methvin/watcher/DirectoryChangeListener.html...
2849[warn] Generating /build/repo/core/target/api/io/methvin/watcher/DirectoryWatcher.html...
2850[warn] Generating /build/repo/core/target/api/io/methvin/watcher/DirectoryWatcher.Builder.html...
2851[warn] Generating /build/repo/core/target/api/io/methvin/watcher/hashing/FileHash.html...
2852[warn] Generating /build/repo/core/target/api/io/methvin/watcher/hashing/FileHasher.html...
2853[warn] Generating /build/repo/core/target/api/io/methvin/watcher/visitor/FileTreeVisitor.html...
2854[warn] Generating /build/repo/core/target/api/io/methvin/watcher/visitor/FileTreeVisitor.Callback.html...
2855[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/jna/FSEventStreamRef.html...
2856[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/MacOSXListeningWatchService.html...
2857[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/MacOSXListeningWatchService.CFRunLoopThread.html...
2858[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/MacOSXListeningWatchService.Config.html...
2859[warn] Generating /build/repo/core/target/api/io/methvin/watcher/hashing/Murmur3F.html...
2860[warn] Generating /build/repo/core/target/api/io/methvin/watcher/OnTimeoutListener.html...
2861[warn] Generating /build/repo/core/target/api/io/methvin/watcher/PathUtils.html...
2862[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/WatchablePath.html...
2863[warn] Generating /build/repo/core/target/api/io/methvin/watcher/package-summary.html...
2864[warn] Generating /build/repo/core/target/api/io/methvin/watcher/package-tree.html...
2865[warn] Generating /build/repo/core/target/api/io/methvin/watcher/changeset/package-summary.html...
2866[warn] Generating /build/repo/core/target/api/io/methvin/watcher/changeset/package-tree.html...
2867[warn] Generating /build/repo/core/target/api/io/methvin/watcher/hashing/package-summary.html...
2868[warn] Generating /build/repo/core/target/api/io/methvin/watcher/hashing/package-tree.html...
2869[warn] Generating /build/repo/core/target/api/io/methvin/watcher/visitor/package-summary.html...
2870[warn] Generating /build/repo/core/target/api/io/methvin/watcher/visitor/package-tree.html...
2871[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/package-summary.html...
2872[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/package-tree.html...
2873[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/jna/package-summary.html...
2874[warn] Generating /build/repo/core/target/api/io/methvin/watchservice/jna/package-tree.html...
2875[warn] Generating /build/repo/core/target/api/constant-values.html...
2876[warn] Generating /build/repo/core/target/api/serialized-form.html...
2877[warn] Generating /build/repo/core/target/api/overview-tree.html...
2878[warn] Generating /build/repo/core/target/api/index.html...
2879[warn] Building index for all classes...
2880[warn] Generating /build/repo/core/target/api/allclasses-index.html...
2881[warn] Generating /build/repo/core/target/api/allpackages-index.html...
2882[warn] Generating /build/repo/core/target/api/index-all.html...
2883[warn] Generating /build/repo/core/target/api/overview-summary.html...
2884[warn] Generating /build/repo/core/target/api/help-doc.html...
2885[info] Main Java API documentation successful.
2886[info] :: delivering :: io.methvin#directory-watcher;0.18.0 :: 0.18.0 :: release :: Fri Apr 04 11:21:11 CEST 2025
2887[info] delivering ivy file to /build/repo/core/target/ivy-0.18.0.xml
2888[info] published directory-watcher to /root/.ivy2/local/io.methvin/directory-watcher/0.18.0/poms/directory-watcher.pom
2889[info] published directory-watcher to /root/.ivy2/local/io.methvin/directory-watcher/0.18.0/jars/directory-watcher.jar
2890[info] published directory-watcher to /root/.ivy2/local/io.methvin/directory-watcher/0.18.0/srcs/directory-watcher-sources.jar
2891[info] published directory-watcher to /root/.ivy2/local/io.methvin/directory-watcher/0.18.0/docs/directory-watcher-javadoc.jar
2892[info] published ivy to /root/.ivy2/local/io.methvin/directory-watcher/0.18.0/ivys/ivy.xml
2893
2894************************
2895Build summary:
2896[{
2897 "module": "directory-watcher-better-files",
2898 "compile": {"status": "ok", "tookMs": 7962, "warnings": 0, "errors": 0, "sourceVersion": "3.7-migration"},
2899 "doc": {"status": "ok", "tookMs": 1430, "files": 336, "totalSizeKb": 6296},
2900 "test-compile": {"status": "ok", "tookMs": 2787, "warnings": 0, "errors": 0, "sourceVersion": "3.7-migration"},
2901 "test": {"status": "skipped", "tookMs": 0, "passed": 0, "failed": 0, "ignored": 0, "skipped": 0, "total": 0, "byFramework": []},
2902 "publish": {"status": "ok", "tookMs": 933},
2903 "metadata": {
2904 "crossScalaVersions": ["3.2.2", "2.13.10", "2.12.10"]
2905}
2906},{
2907 "module": "directory-watcher",
2908 "compile": {"status": "ok", "tookMs": 60, "warnings": 0, "errors": 0, "sourceVersion": "3.7-migration"},
2909 "doc": {"status": "ok", "tookMs": 1084, "files": 69, "totalSizeKb": 781},
2910 "test-compile": {"status": "ok", "tookMs": 649, "warnings": 0, "errors": 0, "sourceVersion": "3.7-migration"},
2911 "test": {"status": "skipped", "tookMs": 0, "passed": 0, "failed": 0, "ignored": 0, "skipped": 0, "total": 0, "byFramework": []},
2912 "publish": {"status": "ok", "tookMs": 622},
2913 "metadata": {
2914 "crossScalaVersions": ["3.2.2"]
2915}
2916}]
2917************************
2918[success] Total time: 22 s, completed Apr 4, 2025, 11:21:11 AM
2919Checking patch build.sbt...
2920Applied patch build.sbt cleanly.