Skip to content

Instantly share code, notes, and snippets.

@setzer22
Created April 17, 2020 09:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save setzer22/af1197b366f562408fae3e5aaa6a837a to your computer and use it in GitHub Desktop.
Save setzer22/af1197b366f562408fae3e5aaa6a837a to your computer and use it in GitHub Desktop.
Clojure: Find out the namespaces that are not transitive dependencies of a namespace in your project
;; Meant to be run on a REPL, this small script will find all the namespaces that are not transitively required
;; by a parent ns. This may be useful if you need to extract a small application from a huge monolithic project.
;; This code has been adapted from https://github.com/hilverd/lein-ns-dep-graph and distributed under the same license.
;; Note that this only looks at the ns declarations, but has no way to detect dependencies that are dynamically built
;; (e.g. by requiring a symbol created from a string using a plain `require`).
(do
(import [java.io PushbackReader])
(require '[clojure.java.io :as io])
(require '[clojure.set :as set])
(require '[clojure.edn :as edn])
(require '[clojure.tools.namespace.file :as ns-file])
(require '[clojure.tools.namespace.track :as ns-track])
(require '[clojure.tools.namespace.find :as ns-find])
(require '[clojure.tools.namespace.dependency :as ns-dep]))
(defn transitive-deps-of [source-paths, ns-parents]
(let [source-files (apply set/union
(map #(ns-find/find-sources-in-dir %)
(file-seq source-paths)))
tracker (ns-file/add-files {} source-files)
dep-graph (tracker ::ns-track/deps)
ns-names (set (map (comp second ns-file/read-file-ns-decl)
source-files))
part-of-project? (partial contains? ns-names)
part-of-parents? #(or (empty? ns-parents)
(contains? ns-parents %)
(boolean (seq (set/intersection ns-parents (ns-dep/transitive-dependents dep-graph %)))))
nodes (->> (ns-dep/nodes dep-graph)
(filter part-of-project?)
(filter part-of-parents?))]
nodes))
(let [source-paths (io/file "/path/to/my/project/src/main/clojure/")]
(set/difference
(set (transitive-deps-of source-paths #{'my.parent.ns}))
(set (transitive-deps-of source-paths #{}))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment