-
-
Notifications
You must be signed in to change notification settings - Fork 177
/
fs_watch.clj
84 lines (68 loc) · 2.2 KB
/
fs_watch.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
(ns shadow.cljs.devtools.server.fs-watch
(:require [shadow.build.api :as cljs]
[clojure.core.async :as async :refer (alt!! thread >!!)]
[shadow.cljs.devtools.server.util :as util]
[shadow.cljs.devtools.server.system-bus :as system-bus]
[shadow.cljs.devtools.server.system-msg :as system-msg]
[clojure.java.io :as io]
[clojure.string :as str])
(:import (shadow.util FileWatcher)
(java.io File)))
(defn service? [x]
(and (map? x)
(::service x)))
(defn poll-changes [{:keys [dir watcher]}]
(let [changes (.pollForChanges watcher)]
(when (seq changes)
(->> changes
(map (fn [[name event]]
{:dir dir
:name name
:ext (when-let [x (str/index-of name ".")]
(subs name (inc x)))
:file (io/file dir name)
:event event}))
;; ignore empty files
(remove (fn [{:keys [file]}]
(zero? (.length file))))
))))
(defn watch-loop
[watch-dirs control publish-fn]
(loop []
(alt!!
control
([_]
:terminated)
(async/timeout 500)
([_]
(let [fs-updates
(->> watch-dirs
(mapcat poll-changes)
(into []))]
(when (seq fs-updates)
(publish-fn fs-updates))
(recur)))))
;; shut down watchers when loop ends
(doseq [{:keys [watcher]} watch-dirs]
(.close watcher))
::shutdown-complete)
(defn start [directories file-exts publish-fn]
{:pre [(every? #(instance? File %) directories)
(coll? file-exts)
(every? string? file-exts)]}
(let [control
(async/chan)
watch-dirs
(->> directories
(map (fn [dir]
{:dir dir
:watcher (FileWatcher/create dir (vec file-exts))}))
(into []))]
{::service true
:control control
:watch-dirs watch-dirs
:thread (thread (watch-loop watch-dirs control publish-fn))}))
(defn stop [{:keys [control thread] :as svc}]
{:pre [(service? svc)]}
(async/close! control)
(async/<!! thread))