diff --git a/.travis.yml b/.travis.yml index f11f961d..f27a32d5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,5 @@ script: bin/lein self-install; bin/lein test branches: only: - 1.x - - master notifications: irc: "irc.freenode.org#leiningen" \ No newline at end of file diff --git a/leiningen-core/src/leiningen/core/classpath.clj b/leiningen-core/src/leiningen/core/classpath.clj index e1896702..91957f3d 100644 --- a/leiningen-core/src/leiningen/core/classpath.clj +++ b/leiningen-core/src/leiningen/core/classpath.clj @@ -17,12 +17,12 @@ (defn resolve-dependencies [{:keys [repositories dependencies]}] {:pre [(every? vector? dependencies)]} - (aether/resolve-dependencies :repositories repositories + (aether/resolve-dependencies :repositories (into {} repositories) :coordinates dependencies)) (defn resolve-dev-dependencies [{:keys [repositories dev-dependencies root]}] {:pre [(every? vector? dev-dependencies)]} - (let [files (aether/resolve-dependencies :repositories repositories + (let [files (aether/resolve-dependencies :repositories (into {} repositories) :coordinates dev-dependencies)] (when (seq dev-dependencies) (.mkdirs (io/file root "lib/dev"))) diff --git a/leiningen-core/src/leiningen/core/eval.clj b/leiningen-core/src/leiningen/core/eval.clj index 6dcc828f..f4af9c21 100644 --- a/leiningen-core/src/leiningen/core/eval.clj +++ b/leiningen-core/src/leiningen/core/eval.clj @@ -103,8 +103,7 @@ ;; (compile project))) ;; (when (or (empty? (find-deps-files project)) checksum-deps) ;; (deps project)) - ;; (when compile-path - ;; (.mkdirs (io/file compile-path))) + (.mkdirs (io/file compile-path)) ) (defn eval-in-leiningen [project form-string] diff --git a/leiningen-core/src/leiningen/core/ns.clj b/leiningen-core/src/leiningen/core/ns.clj index 714531a6..65a4a5ef 100644 --- a/leiningen-core/src/leiningen/core/ns.clj +++ b/leiningen-core/src/leiningen/core/ns.clj @@ -1,7 +1,8 @@ (ns leiningen.core.ns "Inspired by clojure.contrib.find-namespaces, but trimmed down to just what Leiningen needs." - (:require [clojure.java.io :as io]) + (:require [clojure.java.io :as io] + [clojure.string :as string]) (:import (java.util.jar JarFile) (java.io File BufferedReader PushbackReader InputStreamReader))) @@ -63,3 +64,9 @@ (io/file dir (.replaceAll prefix "\\." "/")))) (filter #(and % (.startsWith (name %) prefix)) (mapcat namespaces-in-jar (filter jar? classpath-files))))) + +(defn path-for [n] + (str (-> (str n) + (.replace \- \_) + (.replace \. \/)) + ".clj")) \ No newline at end of file diff --git a/src/leiningen/clean.clj b/src/leiningen/clean.clj index 1b7bde25..5d377c9f 100644 --- a/src/leiningen/clean.clj +++ b/src/leiningen/clean.clj @@ -16,4 +16,4 @@ Raise an exception if any deletion fails unless silently is true." (defn clean "Remove all files from project's target-dir." [project] - (delete-file-recursively (:target-dir project) :silently)) + (delete-file-recursively (:target-path project) :silently)) diff --git a/src/leiningen/compile.clj b/src/leiningen/compile.clj index 0861e8f9..61c6796e 100644 --- a/src/leiningen/compile.clj +++ b/src/leiningen/compile.clj @@ -1,12 +1,10 @@ (ns leiningen.compile "Compile Clojure source into .class files." - (:use [leiningen.deps :only [deps find-deps-files]] - [leiningen.core :only [defdeprecated user-settings]] - [leiningen.javac :only [javac]] - [leiningen.classpath :only [get-classpath-string]] - [clojure.java.io :only [file resource reader copy]] - [leiningen.util.ns :only [namespaces-in-dir]]) - (:require [leiningen.util.paths :as paths]) + (:require [leiningen.core.user :as user] + [leiningen.core.ns :as ns] + [leiningen.core.eval :as eval] + ;; [leiningen.javac :as javac] + [clojure.java.io :as io]) (:refer-clojure :exclude [compile]) (:import (java.io PushbackReader))) @@ -16,40 +14,28 @@ (def ^{:dynamic true} *skip-auto-compile* false) -(defn- regex? - "Returns true if we have regex class" - [str-or-re] +(defn- regex? [str-or-re] (instance? java.util.regex.Pattern str-or-re)) -(defn- separate - "copy of separate function from c.c.seq-utils" - [f s] - [(filter f s) (filter (complement f) s) ]) - -(defn- find-namespaces-by-regex - "Trying to generate list of namespaces, matching to given regexs" - [project nses] - (let [[res syms] (separate regex? nses)] +(defn- find-namespaces-by-regex [project nses] + (let [[res syms] ((juxt filter remove) regex? nses)] (if (seq res) - (set (for [re res n (namespaces-in-dir (:source-path project)) + (set (for [re res n (ns/namespaces-in-dir (:source-path project)) :when (re-find re (name n))] n)) nses))) - (defn- compile-main? [{:keys [main source-path] :as project}] (and main (not (:skip-aot (meta main))) - (.exists (file source-path (paths/ns->path main))))) + (.exists (io/file source-path (ns/path-for main))))) (defn compilable-namespaces "Returns a seq of the namespaces that are compilable, regardless of whether their class files are present and up-to-date." [project] - (when (:namespaces project) - (println "WARNING: :namespaces in project.clj is deprecated; use :aot.")) - (let [nses (or (:aot project) (:namespaces project)) + (let [nses (:aot project) nses (if (= :all nses) - (namespaces-in-dir (:source-path project)) + (ns/namespaces-in-dir (:source-path project)) (find-namespaces-by-regex project nses))] (if (compile-main? project) (conj nses (:main project)) @@ -61,141 +47,14 @@ [project] (filter (fn [n] - (let [clj-path (paths/ns->path n) - class-file (file (:compile-path project) - (.replace clj-path "\\.clj" "__init.class"))] + (let [clj-path (ns/path-for n) + class-file (io/file (:compile-path project) + (.replace clj-path "\\.clj" "__init.class"))] (or (not (.exists class-file)) - (> (.lastModified (file (:source-path project) clj-path)) + (> (.lastModified (io/file (:source-path project) clj-path)) (.lastModified class-file))))) (compilable-namespaces project))) - ;; eval-in-project - -(defdeprecated get-os paths/get-os) - -(defdeprecated get-os paths/get-arch) - -(defn platform-nullsink [] - (file (if (= :windows (paths/get-os)) - "NUL" - "/dev/null"))) - -(defn- as-str [x] - (if (instance? clojure.lang.Named x) - (name x) - (str x))) - -(defn- d-property [[k v]] - (format "-D%s=%s" (as-str k) v)) - -(defn ^{:internal true} get-jvm-args [project] - (let [native-arch-path (paths/native-arch-path project)] - `(~@(let [opts (System/getenv "JVM_OPTS")] - (when (seq opts) [opts])) - ~@(:jvm-opts project) - ~@(:jvm-opts (user-settings)) - ~@(map d-property {:clojure.compile.path (:compile-path project) - (str (:name project) ".version") (:version project) - :clojure.debug (boolean (or (System/getenv "DEBUG") - (:debug project)))}) - ~@(when (and native-arch-path (.exists native-arch-path)) - [(d-property [:java-library-path native-arch-path])])))) - -(defn- injected-forms [] - (with-open [rdr (-> "robert/hooke.clj" resource reader PushbackReader.)] - `(do (ns ~'leiningen.util.injected) - ~@(doall (take 6 (rest (repeatedly #(read rdr))))) - (ns ~'user)))) - -(defn get-readable-form [java project form init] - (let [form `(do ~init - ~(:project-init project) - ~@(let [user-clj (file (paths/leiningen-home) "user.clj")] - (if (.exists user-clj) - [(list 'load-file (str user-clj))])) - ~(injected-forms) - (set! ~'*warn-on-reflection* - ~(:warn-on-reflection project)) - (try ~form - ;; non-daemon threads will prevent process from exiting; - ;; see http://tinyurl.com/2ueqjkl - (finally - (when (and ~(:shutdown-agents project false) - (not= "1.5" (System/getProperty - "java.specification.version"))) - (shutdown-agents)))))] - ;; work around java's command line handling on windows - ;; http://bit.ly/9c6biv This isn't perfect, but works for what's - ;; currently being passed; see - ;; http://www.perlmonks.org/?node_id=300286 for some of the - ;; landmines involved in doing it properly - (if (and (= (paths/get-os) :windows) (not (:eval-in-leiningen project))) - (pr-str (pr-str form)) - (pr-str form)))) - -(defn prep [{:keys [compile-path checksum-deps] :as project} skip-auto-compile] - (when (and (not (or *skip-auto-compile* skip-auto-compile)) compile-path - (empty? (.list (file compile-path)))) - (binding [*silently* true] - (compile project))) - (when (or (empty? (find-deps-files project)) checksum-deps) - (deps project)) - (when compile-path - (.mkdirs (file compile-path)))) - -(defn eval-in-leiningen [project form-string] - ;; bootclasspath workaround: http://dev.clojure.org/jira/browse/CLJ-673 - (require '[clojure walk repl]) - (require '[clojure.java io shell browse]) - (when (:debug project) - (System/setProperty "clojure.debug" "true")) - ;; need to at least pretend to return an exit code - (try (binding [*warn-on-reflection* (:warn-on-reflection project), *ns* *ns*] - (eval (read-string form-string))) - 0 - (catch Exception e - (.printStackTrace e) - 1))) - -(defn- pump [reader out] - (let [buffer (make-array Character/TYPE 1000)] - (loop [len (.read reader buffer)] - (when-not (neg? len) - (.write out buffer 0 len) - (.flush out) - (Thread/sleep 100) - (recur (.read reader buffer)))))) - -;; clojure.java.shell/sh doesn't let you stream out/err -(defn sh [& cmd] - (let [proc (.exec (Runtime/getRuntime) (into-array cmd))] - (with-open [out (reader (.getInputStream proc)) - err (reader (.getErrorStream proc))] - (let [pump-out (doto (Thread. #(pump out *out*)) .start) - pump-err (doto (Thread. #(pump err *err*)) .start)] - (.join pump-out) - (.join pump-err)) - (.waitFor proc)))) - -(defn eval-in-subprocess [project form-string] - (apply sh `(~(or (System/getenv "JAVA_CMD") "java") - "-cp" ~(get-classpath-string project) - ~@(get-jvm-args project) - "clojure.main" "-e" ~form-string))) - -(defn eval-in-project - "Executes form in an isolated classloader with the classpath and compile path - set correctly for the project. If the form depends on any requires, put them - in the init arg to avoid the Gilardi Scenario: http://technomancy.us/143" - [project form & [handler skip-auto-compile init]] - (when skip-auto-compile - (println "WARNING: eval-in-project's skip-auto-compile arg is deprecated.")) - (prep project skip-auto-compile) - (let [form-string (get-readable-form nil project form init)] - (if (:eval-in-leiningen project) - (eval-in-leiningen project form-string) - (eval-in-subprocess project form-string)))) - ;; .class file cleanup (defn- has-source-package? @@ -206,16 +65,16 @@ (->> f, (iterate #(.getParentFile %)), (take-while identity), rest, (split-with #(not (re-find #"^proxy\$" (.getName %)))))] - (.isDirectory (file (.replace (.getPath (or proxy-mod-parent parent)) - (:compile-path project) - source-path)))))) + (.isDirectory (io/file (.replace (.getPath (or proxy-mod-parent parent)) + (:compile-path project) + source-path)))))) (defn- class-in-project? [project f] (or (has-source-package? project f (:source-path project)) (has-source-package? project f (:java-source-path project)) - (.exists (file (str (.replace (.getParent f) - (:compile-path project) - (:source-path project)) ".clj"))))) + (.exists (io/file (str (.replace (.getParent f) + (:compile-path project) + (:source-path project)) ".clj"))))) (defn- relative-path [project f] (let [root-length (if (= \/ (last (:compile-path project))) @@ -237,7 +96,7 @@ (defn clean-non-project-classes [project] (when (:clean-non-project-classes project) - (doseq [f (file-seq (file (:compile-path project))) + (doseq [f (file-seq (io/file (:compile-path project))) :when (and (.isFile f) (not (whitelisted-class? project f)) (blacklisted-class? project f))] @@ -260,17 +119,17 @@ Uses the namespaces specified under :aot in project.clj or those given as command-line arguments." ([project] - (when (:java-source-path project) - (javac project)) + ;; (when (:java-source-path project) + ;; (javac/javac project)) (if (seq (compilable-namespaces project)) (if-let [namespaces (seq (stale-namespaces project))] (binding [*skip-auto-compile* true] (try - (if (zero? (eval-in-project project - `(doseq [namespace# '~namespaces] - (when-not ~*silently* - (println "Compiling" namespace#)) - (clojure.core/compile namespace#)))) + (if (zero? (eval/eval-in-project project + `(doseq [namespace# '~namespaces] + (when-not ~*silently* + (println "Compiling" namespace#)) + (clojure.core/compile namespace#)))) (success "Compilation succeeded.") (failure "Compilation failed.")) (finally (clean-non-project-classes project)))) diff --git a/todo.org b/todo.org index 19429e3f..66b77b05 100644 --- a/todo.org +++ b/todo.org @@ -7,6 +7,44 @@ Leiningen TODOs See also https://github.com/technomancy/leiningen/issues +* For 2.0.0 +** Big Picture + - [ ] Finish designing and implement profiles + - [ ] figure out how old no-dev functionality fits in + - [ ] Further design on Project Middleware + - [ ] In-process eval-in-project + - [ ] Dynamic recalculating of classpath via pomegranate + - [ ] Redesign repl task, possibly around nREPL +** Other stuff + - [ ] Move pom generation to pomegranate or leiningen + - [ ] Better consistency/docs around user/settings + - [ ] Non-transitive AOT + - [ ] lint/check mode for lein compile + - [ ] ns-level test selectors + - [ ] More flexibility for jarring + - [ ] Mirror/proxy support, also for search indices + - [ ] Allow disabling of all injected code + - [ ] Drop clojars snapshots from default repos +** Adapt existing tasks to new API + - [ ] classpath + - [X] clean + - [ ] compile + - [ ] deploy + - [ ] deps (mostly done in leiningen.core.classpath) + - [ ] help + - [ ] install + - [ ] jar + - [ ] javac (can we do this without ant?) + - [ ] new (merge from lein-newnew) + - [ ] plugin + - [ ] pom (steal from depot) + - [ ] repl (figure out nrepl integration) + - [ ] retest + - [ ] run + - [ ] search + - [ ] test + - [ ] trampoline + - [ ] uberjar * For 1.6.2 - [X] resources with eval-in-leiningen (#248) - [X] fix :omit-default-repositories wrt central (#211)