clojure.tools.namespace.reload.clj Maven / Gradle / Ivy
;; Copyright (c) Stuart Sierra, 2012. All rights reserved. The use and
;; distribution terms for this software are covered by the Eclipse
;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
;; which can be found in the file epl-v10.html at the root of this
;; distribution. By using this software in any fashion, you are
;; agreeing to be bound by the terms of this license. You must not
;; remove this notice, or any other, from this software.
(ns ^{:author "Stuart Sierra"
:doc "Force reloading namespaces on demand or through a
dependency tracker"}
clojure.tools.namespace.reload
(:require [clojure.tools.namespace.track :as track]))
(defn remove-lib
"Remove lib's namespace and remove lib from the set of loaded libs."
[lib]
(remove-ns lib)
(dosync (alter @#'clojure.core/*loaded-libs* disj lib)))
(defn track-reload-one
"Executes the next pending unload/reload operation in the dependency
tracker. Returns the updated dependency tracker. If reloading caused
an error, it is captured as ::error and the namespace which caused
the error is ::error-ns."
[tracker]
(let [{unload ::track/unload, load ::track/load} tracker]
(cond
(seq unload)
(let [n (first unload)]
(remove-lib n)
(update-in tracker [::track/unload] rest))
(seq load)
(let [n (first load)]
(try (require n :reload)
(update-in tracker [::track/load] rest)
(catch Throwable t
(assoc tracker
::error t ::error-ns n ::track/unload load))))
:else
tracker)))
(defn track-reload
"Executes all pending unload/reload operations on dependency tracker
until either an error is encountered or there are no more pending
operations."
[tracker]
(loop [tracker (dissoc tracker ::error ::error-ns)]
(let [{error ::error, unload ::track/unload, load ::track/load} tracker]
(if (and (not error)
(or (seq load) (seq unload)))
(recur (track-reload-one tracker))
tracker))))