Share your thoughts in the 2024 State of Clojure Survey!

Welcome! Please see the About page for a little more info on how this works.

+1 vote
in tools.namespace by

Hey,

At my organisation, we use Component and would like to start using the reloaded workflow to reload the code more easily.

The problem we’re facing is that our dev classpath contains too much. In addition to the app proper (loaded by (require 'our-org.repl)), there are tests and some one-off code: migrations and illustrative REPL sessions that we keep around as documentation.

Some of these auxiliary namespaces have names that don’t match their location in the filesystem, so they are not loaded correctly by tools.namespace. We’d like to prevent them from being reloaded at all, even though they are present on the classpath.

We could use clojure.tools.namespace.repl/set-refresh-dirs, but I feel this is clunky (need to explicitly opt-in for directories) and not quite expressive enough. What we’d really want is to reload only the namespaces that are (possibly indirect) dependencies of our-org.repl.

To this end, I’ve monkey-patched tools-namespace:

(defn relevant-deps [deps ns]
  (conj
   (ns.dependency/transitive-dependencies deps ns)
   ns))

(alter-var-root
 #'ns.repl/remove-disabled
 (fn [orig-impl]
   (fn [{:keys [::ns.track/deps] :as tracker}]
     (-> tracker
         (orig-impl)
         (update ::ns.track/unload (partial filter (loaded-libs)))
         (update ::ns.track/load
                 #(set/intersection (set %1) %2)
                 (relevant-deps deps 'our-org.repl))))))

This works, but is obviously kludgy. Is there a better way to achieve the same goal? Perhaps the functionality of restricting dependencies could be added to tools.namespace?

2 Answers

+1 vote
by

A quite relevant post I've made some time ago: https://ask.clojure.org/index.php/10277/preventing-clojure-namespace-refresh-loading-namespaces

I would very much like to have such functionality built into tools.namespace.

...