|
2 | 2 | "Watch deps.edn for changes"
|
3 | 3 | (:require [clojure.java.classpath :as cp]
|
4 | 4 | [clojure.string :as str]
|
| 5 | + [clojure.java.io :as io] |
5 | 6 | [clojure.tools.deps.alpha :as deps]
|
6 | 7 | [lambdaisland.classpath :as licp]
|
7 |
| - [nextjournal.beholder :as beholder])) |
| 8 | + [nextjournal.beholder :as beholder]) |
| 9 | + (:import java.util.regex.Pattern |
| 10 | + java.nio.file.LinkOption |
| 11 | + java.nio.file.Paths)) |
8 | 12 |
|
9 | 13 | (def watcher (atom nil))
|
10 | 14 |
|
11 |
| -(defn- on-event [opts {:keys [type path]}] |
12 |
| - (when (and (= :modify type) |
13 |
| - ;; On Mac the path will be absolute and include the watched dir, |
14 |
| - ;; e.g. `/Users/x/project/./deps.edn` |
15 |
| - ;; On other systems it seems to be relative, like `./deps.edn` |
16 |
| - (str/ends-with? (str path) "./deps.edn")) |
17 |
| - (println "✨ Reloading deps.edn ✨") |
18 |
| - (let [new-paths (remove (set (map str (cp/system-classpath))) |
19 |
| - (:classpath-roots (deps/create-basis opts)))] |
20 |
| - (doseq [path new-paths] |
21 |
| - (println "- " path)) |
22 |
| - (licp/install-priority-loader! new-paths)))) |
| 15 | +(defn canonical-path [p] |
| 16 | + (.toRealPath (Paths/get p (into-array String [])) (into-array LinkOption []))) |
| 17 | + |
| 18 | +(def process-root-path (canonical-path ".")) |
| 19 | + |
| 20 | +(defn- on-event [deps-path opts {:keys [type path]}] |
| 21 | + (locking watcher |
| 22 | + (when (and (= :modify type) |
| 23 | + ;; Before we used "." as the watch path, resulting in a |
| 24 | + ;; difference between mac, where the path would look like this |
| 25 | + ;; `/Users/x/project/./deps.edn`, vs Linux where the path would |
| 26 | + ;; look like this `./deps.edn`. |
| 27 | + ;; |
| 28 | + ;; We now turn `"."` into a canonical path before starting the |
| 29 | + ;; watcher, which means we get fully qualified filenames for both |
| 30 | + ;; in this equality check. |
| 31 | + (= path deps-path)) |
| 32 | + (try |
| 33 | + (println "✨ Reloading" |
| 34 | + (str (.relativize process-root-path path)) |
| 35 | + "✨") |
| 36 | + (let [added-paths (remove (set (map str (cp/system-classpath))) |
| 37 | + (:classpath-roots (deps/create-basis opts)))] |
| 38 | + (doseq [path added-paths] |
| 39 | + (println "+" (str/replace path #"^.*/\.m2/repository/" ""))) |
| 40 | + (licp/install-priority-loader! added-paths)) |
| 41 | + (catch Exception e |
| 42 | + (println "Error while reloading deps.edn") |
| 43 | + (println e)))))) |
23 | 44 |
|
24 | 45 | (defn start!
|
25 | 46 | "Start a file system watcher to pick up changes in `deps.edn'
|
|
35 | 56 | (swap! watcher
|
36 | 57 | (fn [w]
|
37 | 58 | (when w
|
38 |
| - (println "Stopping existing `deps.edn' watcher") |
39 |
| - (beholder/stop w)) |
40 |
| - (beholder/watch (partial on-event opts) ".")))) |
| 59 | + (println "Stopping existing `deps.edn' watchers") |
| 60 | + (run! beholder/stop w)) |
| 61 | + (let [basis (deps/create-basis opts) |
| 62 | + roots (cons (str process-root-path) |
| 63 | + (when (:include-local-roots? opts) |
| 64 | + (->> (vals (:libs basis)) |
| 65 | + (keep :local/root) |
| 66 | + (map canonical-path) |
| 67 | + (map str))))] |
| 68 | + (doall |
| 69 | + (for [root roots] |
| 70 | + (beholder/watch |
| 71 | + (partial #'on-event (Paths/get root (into-array String ["deps.edn"])) opts) |
| 72 | + root))))))) |
41 | 73 |
|
42 | 74 | (defn stop!
|
43 | 75 | "Stop a previously started watcher"
|
|
48 | 80 | (beholder/stop w))
|
49 | 81 | nil)))
|
50 | 82 |
|
51 |
| - |
52 | 83 | (comment
|
53 |
| - (start! {:aliases [:dev]})) |
| 84 | + (start! {:aliases [:dev]}) |
| 85 | + |
| 86 | + (deps/create-basis {:aliases [:backend] |
| 87 | + :extra '{cider/cider-nrepl #:mvn{:version "0.28.5"} |
| 88 | + refactor-nrepl/refactor-nrepl #:mvn{:version "3.5.2"}}})) |
0 commit comments