Permalink
Browse files

Moved things around

  • Loading branch information...
1 parent 484491c commit 09027de6c933e748f60abfd6afde3f3e7edfc458 @marick committed Dec 23, 2012
View
@@ -9,6 +9,7 @@
[bultitude "0.1.7"]
[leiningen-core "2.0.0-preview10"]
[swiss-arrows "0.1.0"]
+ [org.clojure/tools.namespace "0.2.2"]
[gui-diff "0.3.9"]])
(defproject midje "1.5-alpha4"
@@ -19,8 +20,7 @@
:profiles {:dev {:dependencies [[slamhound "1.2.0"]
[jonase/kibit "0.0.3"]
- [jonase/eastwood "0.0.2"]
- [org.clojure/tools.namespace "0.2.2"]]
+ [jonase/eastwood "0.0.2"]]
:plugins [[lein-midje "2.0.3"]]}
:1.2.0 {:dependencies [[org.clojure/clojure "1.2.0"]]}
:1.2.1 {:dependencies [[org.clojure/clojure "1.2.1"]]}
@@ -0,0 +1,123 @@
+(ns ^{:doc "What we know about the changing project file/namespace tree."}
+ midje.internal-ideas.project-state
+ (:use [midje.util.form-utils :only [invert]]
+ [swiss-arrows.core :only [-<>]]
+ [bultitude.core :only [namespaces-in-dir namespaces-on-classpath]])
+ (:require [midje.util.ecosystem :as ecosystem]
+ midje.util.backwards-compatible-utils))
+
+(ecosystem/when-1-3+
+
+ (require '[clojure.tools.namespace.repl :as nsrepl]
+ '[clojure.tools.namespace.dir :as nsdir]
+ '[clojure.tools.namespace.track :as nstrack]
+ '[clojure.tools.namespace.reload :as nsreload]
+ '[leiningen.core.project :as project])
+
+
+;;; Querying the project tree
+
+ (defn directories []
+ (try
+ (let [project (project/read)]
+ (concat (:test-paths project) (:source-paths project)))
+ (catch java.io.FileNotFoundException e
+ ["test"])))
+
+ (defn namespaces []
+ (mapcat namespaces-in-dir (directories)))
+
+ (defn unglob-partial-namespaces [namespaces]
+ (mapcat #(if (= \* (last %))
+ (namespaces-on-classpath :prefix (apply str (butlast %)))
+ [(symbol %)])
+ (map str namespaces)))
+
+
+;;; Responding to changed files
+
+
+ (defonce watched-directories (directories))
+ (defonce nstracker (atom (nstrack/tracker)))
+
+ (def unload-key :clojure.tools.namespace.track/unload)
+ (def load-key :clojure.tools.namespace.track/load)
+ (def filemap-key :clojure.tools.namespace.file/filemap)
+ (def deps-key :clojure.tools.namespace.track/deps)
+ (def time-key :clojure.tools.namespace.dir/time)
+ (def next-time-key :next-time)
+
+ (defn file-modification-time [file]
+ (.lastModified file))
+
+ (defn latest-modification-time [nstracker]
+ (let [ns-to-file (invert (filemap-key nstracker))
+ relevant-files (map ns-to-file (load-key nstracker))]
+ (apply max (time-key nstracker)
+ (map file-modification-time relevant-files))))
+
+
+ (defn autotest-augment-tracker [nstracker]
+ (assoc nstracker next-time-key (latest-modification-time nstracker)))
+
+ (defn autotest-next-tracker [nstracker]
+ (assoc nstracker
+ time-key (next-time-key nstracker)
+ unload-key []
+ load-key []))
+
+ (defn first-to-load [nstracker]
+ (first (load-key nstracker)))
+
+ (defn without-first-to-load [nstracker]
+ (assoc nstracker load-key (rest (load-key nstracker))))
+
+ (defn without-first-to-load-and-dependents [nstracker]
+ (let [[first & remainder] (load-key nstracker)
+ first-dependents (get-in nstracker [deps-key :dependents first] #{})
+ surviving-remainder (remove first-dependents remainder)]
+ (assoc nstracker load-key surviving-remainder)))
+
+
+ (defn work-free-tracker? [tracker]
+ (empty? (load-key tracker)))
+
+
+ (defn show-failure [the-ns throwable]
+ (println "LOAD FAILURE for" (ns-name the-ns))
+ (println (.getMessage throwable))
+ (when (ecosystem/running-in-repl?)
+ (println "The exception has been stored in #'*e, so `pst` will show the stack trace.")
+ (if (thread-bound? #'*e)
+ (set! *e throwable)
+ (alter-var-root #'clojure.core/*e (constantly throwable)))))
+
+
+ (defn load-one [nstracker]
+ (let [the-ns (first-to-load nstracker)
+ result (try (require the-ns :reload)
+ (catch Throwable t t))]
+ (if (isa? (class result) Throwable)
+ (do (show-failure the-ns result)
+ (without-first-to-load-and-dependents nstracker))
+ (without-first-to-load nstracker))))
+
+ (defn obey-tracker [nstracker]
+ (if (work-free-tracker? nstracker)
+ nstracker
+ (recur (load-one nstracker))))
+
+ (defn react-to-any-changed-files! [namespace-finder]
+ (swap! nstracker #(-<> %
+ (apply namespace-finder <> watched-directories)
+ autotest-augment-tracker
+ obey-tracker
+ autotest-next-tracker)))
+
+ (defn load-everything []
+ (react-to-any-changed-files! nsdir/scan-all))
+
+ (defn load-changed [& args]
+ (react-to-any-changed-files! nsdir/scan))
+
+)
View
@@ -3,15 +3,17 @@
midje.repl
(:use clojure.pprint)
(:require midje.sweet
+ [midje.doc :as doc]
+ [midje.config :as config]
[midje.ideas.facts :as fact]
- [midje.internal-ideas.compendium :as compendium]
[midje.ideas.reporting.levels :as levelly]
[midje.ideas.metadata :as metadata]
- [midje.doc :as doc]
- [midje.config :as config]
+ [midje.internal-ideas.compendium :as compendium]
+ [midje.internal-ideas.project-state :as project-state]
[midje.util.form-utils :as form]
[midje.util.colorize :as color]
[midje.util.ecosystem :as ecosystem]
+ [midje.util.scheduling :as scheduling]
[midje.util.namespace :as namespace]))
(when (and (ecosystem/running-in-repl?) (ecosystem/clojure-1-2-X?))
@@ -142,9 +144,9 @@
(merge base
{:disk-command (:given-namespace-args base)}
(if (:all? base)
- {:namespaces-to-use (ecosystem/project-namespaces)
+ {:namespaces-to-use (project-state/namespaces)
:memory-command [:all]}
- (let [expanded (ecosystem/unglob-partial-namespaces (:given-namespace-args base))]
+ (let [expanded (project-state/unglob-partial-namespaces (:given-namespace-args base))]
{:namespaces-to-use expanded
:memory-command expanded})))))
@@ -360,13 +362,34 @@
;;; Autotest
-(defmulti autotest (fn [& args]
- (or ((set args) :stop)
- ((set args) :pause)
- ((set args) :resume)
- (pos? (count args)))))
+(def ^{:private true, :testable true}
+ autotest-interval (atom 500))
+
+(defmulti autotest
+ "`autotest` checks frequently for changed files. It reloads those files
+ and all files that depend on them. Since test files depend on source files,
+ that typically results in facts being reloaded and checked.
+
+ `autotest` monitors all the files in the project.clj's :source-paths
+ and :test-paths. If you don't have a project.clj file, don't use
+ autotest.
+
+ `autotest` can be given an :each argument to control how often
+ it checks for modified files. The argument is in milliseconds:
+
+ (autotest :each 1000) ; check each second.
-(def autotest-interval (atom 5000))
+ `autotest` can take special keyword arguments:
+
+ (autotest :stop) ; stop checking
+ (autotest :pause) ; pause checking
+ (autotest :resume) ; continue after a :pause
+ "
+ (fn [& args]
+ (or ((set args) :stop)
+ ((set args) :pause)
+ ((set args) :resume)
+ (pos? (count args)))))
(defmethod autotest :default []
(autotest :each @autotest-interval))
@@ -375,19 +398,17 @@
(let [options (apply hash-map args)]
(swap! autotest-interval #(or (:each options) %))
(println)
- (ecosystem/load-everything)
+ (project-state/load-everything)
(autotest :resume)))
(defmethod autotest :resume [_]
- (ecosystem/schedule :autotest ecosystem/load-changed @autotest-interval)
+ (scheduling/schedule :autotest project-state/load-changed @autotest-interval)
true)
(defmethod autotest :stop [_]
- (ecosystem/stop :autotest)
+ (scheduling/stop :autotest)
true)
(defmethod autotest :pause [_]
(autotest :stop))
-
-
)
Oops, something went wrong.

0 comments on commit 09027de

Please sign in to comment.