-
Notifications
You must be signed in to change notification settings - Fork 152
/
util.clj
86 lines (74 loc) · 2.41 KB
/
util.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
83
84
85
86
(ns cljsbuild.util
(:require
[clojure.java.io :as io]
[clojure.string :as string]
[fs.core :as fs])
(:import
(java.io OutputStreamWriter)))
(defn join-paths [& paths]
(apply str (interpose "/" paths)))
(defn filter-by-ext [files types]
(let [ext #(last (string/split % #"\."))]
(filter #(types (ext %)) files)))
(defn find-dir-files [root files types]
(for [file (filter-by-ext files types)]
(join-paths root file)))
(defn find-files [dir types]
(let [iter (fs/iterate-dir dir)]
(mapcat
(fn [[root _ files]]
(find-dir-files root files types))
iter)))
(defn in-threads
"Given a seq and a function, applies the function to each item in a different thread
and returns a seq of the results. Launches all the threads at once."
[f s]
(doall (map deref (doall (map #(future (f %)) s)))))
(defn sleep [ms]
(Thread/sleep ms))
(defn once-every
([ms desc f keep-going]
(while (keep-going)
(try
(f)
(catch Exception e
(println (str "Error " desc ": " e))))
(sleep ms)))
([ms desc f]
(once-every ms desc f (fn [] true))))
(defn- pump-file [reader out]
(let [buffer (make-array Character/TYPE 1000)]
(loop [len (.read reader buffer)]
(when-not (neg? len)
(.write out buffer 0 len)
(.flush out)
(Thread/sleep 100)
(recur (.read reader buffer))))))
(defn- process-pump [process stdout stderr]
(with-open [out (io/reader (.getInputStream process))
err (io/reader (.getErrorStream process))]
(let [pump-out (doto (Thread. #(pump-file out stdout)) .start)
pump-err (doto (Thread. #(pump-file err stderr)) .start)]
(.join pump-out)
(.join pump-err))))
(defn maybe-writer [file fallback]
(if file
(do
(fs/delete file)
(io/writer file))
fallback))
(defn process-start [{:keys [shell stdout stderr]}]
; FIXME: These writers get left open. Not a huge deal, but...
(let [stdout-writer (maybe-writer stdout *out*)
stderr-writer (maybe-writer stderr *err*)
process (.exec (Runtime/getRuntime) (into-array shell))
pumper (future (process-pump process stdout-writer stderr-writer))]
{:kill (fn []
(.destroy process))
:wait (fn []
(.waitFor process)
(deref pumper)
(.exitValue process))}))
(defn sh [command]
(let [process (process-start command)]
((:wait process))))