Merge branch 'master' of git://github.com/technomancy/leiningen
This commit is contained in:
commit
40fdf2419f
7 changed files with 80 additions and 178 deletions
|
@ -3,6 +3,5 @@ script: bin/lein self-install; bin/lein test
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- 1.x
|
- 1.x
|
||||||
- master
|
|
||||||
notifications:
|
notifications:
|
||||||
irc: "irc.freenode.org#leiningen"
|
irc: "irc.freenode.org#leiningen"
|
|
@ -17,12 +17,12 @@
|
||||||
|
|
||||||
(defn resolve-dependencies [{:keys [repositories dependencies]}]
|
(defn resolve-dependencies [{:keys [repositories dependencies]}]
|
||||||
{:pre [(every? vector? dependencies)]}
|
{:pre [(every? vector? dependencies)]}
|
||||||
(aether/resolve-dependencies :repositories repositories
|
(aether/resolve-dependencies :repositories (into {} repositories)
|
||||||
:coordinates dependencies))
|
:coordinates dependencies))
|
||||||
|
|
||||||
(defn resolve-dev-dependencies [{:keys [repositories dev-dependencies root]}]
|
(defn resolve-dev-dependencies [{:keys [repositories dev-dependencies root]}]
|
||||||
{:pre [(every? vector? dev-dependencies)]}
|
{:pre [(every? vector? dev-dependencies)]}
|
||||||
(let [files (aether/resolve-dependencies :repositories repositories
|
(let [files (aether/resolve-dependencies :repositories (into {} repositories)
|
||||||
:coordinates dev-dependencies)]
|
:coordinates dev-dependencies)]
|
||||||
(when (seq dev-dependencies)
|
(when (seq dev-dependencies)
|
||||||
(.mkdirs (io/file root "lib/dev")))
|
(.mkdirs (io/file root "lib/dev")))
|
||||||
|
|
|
@ -103,8 +103,7 @@
|
||||||
;; (compile project)))
|
;; (compile project)))
|
||||||
;; (when (or (empty? (find-deps-files project)) checksum-deps)
|
;; (when (or (empty? (find-deps-files project)) checksum-deps)
|
||||||
;; (deps project))
|
;; (deps project))
|
||||||
;; (when compile-path
|
(.mkdirs (io/file compile-path))
|
||||||
;; (.mkdirs (io/file compile-path)))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
(defn eval-in-leiningen [project form-string]
|
(defn eval-in-leiningen [project form-string]
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
(ns leiningen.core.ns
|
(ns leiningen.core.ns
|
||||||
"Inspired by clojure.contrib.find-namespaces, but trimmed down to
|
"Inspired by clojure.contrib.find-namespaces, but trimmed down to
|
||||||
just what Leiningen needs."
|
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)
|
(:import (java.util.jar JarFile)
|
||||||
(java.io File BufferedReader PushbackReader InputStreamReader)))
|
(java.io File BufferedReader PushbackReader InputStreamReader)))
|
||||||
|
|
||||||
|
@ -63,3 +64,9 @@
|
||||||
(io/file dir (.replaceAll prefix "\\." "/"))))
|
(io/file dir (.replaceAll prefix "\\." "/"))))
|
||||||
(filter #(and % (.startsWith (name %) prefix))
|
(filter #(and % (.startsWith (name %) prefix))
|
||||||
(mapcat namespaces-in-jar (filter jar? classpath-files)))))
|
(mapcat namespaces-in-jar (filter jar? classpath-files)))))
|
||||||
|
|
||||||
|
(defn path-for [n]
|
||||||
|
(str (-> (str n)
|
||||||
|
(.replace \- \_)
|
||||||
|
(.replace \. \/))
|
||||||
|
".clj"))
|
|
@ -16,4 +16,4 @@ Raise an exception if any deletion fails unless silently is true."
|
||||||
(defn clean
|
(defn clean
|
||||||
"Remove all files from project's target-dir."
|
"Remove all files from project's target-dir."
|
||||||
[project]
|
[project]
|
||||||
(delete-file-recursively (:target-dir project) :silently))
|
(delete-file-recursively (:target-path project) :silently))
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
(ns leiningen.compile
|
(ns leiningen.compile
|
||||||
"Compile Clojure source into .class files."
|
"Compile Clojure source into .class files."
|
||||||
(:use [leiningen.deps :only [deps find-deps-files]]
|
(:require [leiningen.core.user :as user]
|
||||||
[leiningen.core :only [defdeprecated user-settings]]
|
[leiningen.core.ns :as ns]
|
||||||
[leiningen.javac :only [javac]]
|
[leiningen.core.eval :as eval]
|
||||||
[leiningen.classpath :only [get-classpath-string]]
|
;; [leiningen.javac :as javac]
|
||||||
[clojure.java.io :only [file resource reader copy]]
|
[clojure.java.io :as io])
|
||||||
[leiningen.util.ns :only [namespaces-in-dir]])
|
|
||||||
(:require [leiningen.util.paths :as paths])
|
|
||||||
(:refer-clojure :exclude [compile])
|
(:refer-clojure :exclude [compile])
|
||||||
(:import (java.io PushbackReader)))
|
(:import (java.io PushbackReader)))
|
||||||
|
|
||||||
|
@ -16,40 +14,28 @@
|
||||||
|
|
||||||
(def ^{:dynamic true} *skip-auto-compile* false)
|
(def ^{:dynamic true} *skip-auto-compile* false)
|
||||||
|
|
||||||
(defn- regex?
|
(defn- regex? [str-or-re]
|
||||||
"Returns true if we have regex class"
|
|
||||||
[str-or-re]
|
|
||||||
(instance? java.util.regex.Pattern str-or-re))
|
(instance? java.util.regex.Pattern str-or-re))
|
||||||
|
|
||||||
(defn- separate
|
(defn- find-namespaces-by-regex [project nses]
|
||||||
"copy of separate function from c.c.seq-utils"
|
(let [[res syms] ((juxt filter remove) regex? nses)]
|
||||||
[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)]
|
|
||||||
(if (seq res)
|
(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))]
|
:when (re-find re (name n))]
|
||||||
n))
|
n))
|
||||||
nses)))
|
nses)))
|
||||||
|
|
||||||
|
|
||||||
(defn- compile-main? [{:keys [main source-path] :as project}]
|
(defn- compile-main? [{:keys [main source-path] :as project}]
|
||||||
(and main (not (:skip-aot (meta main)))
|
(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
|
(defn compilable-namespaces
|
||||||
"Returns a seq of the namespaces that are compilable, regardless of whether
|
"Returns a seq of the namespaces that are compilable, regardless of whether
|
||||||
their class files are present and up-to-date."
|
their class files are present and up-to-date."
|
||||||
[project]
|
[project]
|
||||||
(when (:namespaces project)
|
(let [nses (:aot project)
|
||||||
(println "WARNING: :namespaces in project.clj is deprecated; use :aot."))
|
|
||||||
(let [nses (or (:aot project) (:namespaces project))
|
|
||||||
nses (if (= :all nses)
|
nses (if (= :all nses)
|
||||||
(namespaces-in-dir (:source-path project))
|
(ns/namespaces-in-dir (:source-path project))
|
||||||
(find-namespaces-by-regex project nses))]
|
(find-namespaces-by-regex project nses))]
|
||||||
(if (compile-main? project)
|
(if (compile-main? project)
|
||||||
(conj nses (:main project))
|
(conj nses (:main project))
|
||||||
|
@ -61,141 +47,14 @@
|
||||||
[project]
|
[project]
|
||||||
(filter
|
(filter
|
||||||
(fn [n]
|
(fn [n]
|
||||||
(let [clj-path (paths/ns->path n)
|
(let [clj-path (ns/path-for n)
|
||||||
class-file (file (:compile-path project)
|
class-file (io/file (:compile-path project)
|
||||||
(.replace clj-path "\\.clj" "__init.class"))]
|
(.replace clj-path "\\.clj" "__init.class"))]
|
||||||
(or (not (.exists class-file))
|
(or (not (.exists class-file))
|
||||||
(> (.lastModified (file (:source-path project) clj-path))
|
(> (.lastModified (io/file (:source-path project) clj-path))
|
||||||
(.lastModified class-file)))))
|
(.lastModified class-file)))))
|
||||||
(compilable-namespaces project)))
|
(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
|
;; .class file cleanup
|
||||||
|
|
||||||
(defn- has-source-package?
|
(defn- has-source-package?
|
||||||
|
@ -206,16 +65,16 @@
|
||||||
(->> f, (iterate #(.getParentFile %)),
|
(->> f, (iterate #(.getParentFile %)),
|
||||||
(take-while identity), rest,
|
(take-while identity), rest,
|
||||||
(split-with #(not (re-find #"^proxy\$" (.getName %)))))]
|
(split-with #(not (re-find #"^proxy\$" (.getName %)))))]
|
||||||
(.isDirectory (file (.replace (.getPath (or proxy-mod-parent parent))
|
(.isDirectory (io/file (.replace (.getPath (or proxy-mod-parent parent))
|
||||||
(:compile-path project)
|
(:compile-path project)
|
||||||
source-path))))))
|
source-path))))))
|
||||||
|
|
||||||
(defn- class-in-project? [project f]
|
(defn- class-in-project? [project f]
|
||||||
(or (has-source-package? project f (:source-path project))
|
(or (has-source-package? project f (:source-path project))
|
||||||
(has-source-package? project f (:java-source-path project))
|
(has-source-package? project f (:java-source-path project))
|
||||||
(.exists (file (str (.replace (.getParent f)
|
(.exists (io/file (str (.replace (.getParent f)
|
||||||
(:compile-path project)
|
(:compile-path project)
|
||||||
(:source-path project)) ".clj")))))
|
(:source-path project)) ".clj")))))
|
||||||
|
|
||||||
(defn- relative-path [project f]
|
(defn- relative-path [project f]
|
||||||
(let [root-length (if (= \/ (last (:compile-path project)))
|
(let [root-length (if (= \/ (last (:compile-path project)))
|
||||||
|
@ -237,7 +96,7 @@
|
||||||
|
|
||||||
(defn clean-non-project-classes [project]
|
(defn clean-non-project-classes [project]
|
||||||
(when (: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)
|
:when (and (.isFile f)
|
||||||
(not (whitelisted-class? project f))
|
(not (whitelisted-class? project f))
|
||||||
(blacklisted-class? project f))]
|
(blacklisted-class? project f))]
|
||||||
|
@ -260,17 +119,17 @@
|
||||||
Uses the namespaces specified under :aot in project.clj or those given
|
Uses the namespaces specified under :aot in project.clj or those given
|
||||||
as command-line arguments."
|
as command-line arguments."
|
||||||
([project]
|
([project]
|
||||||
(when (:java-source-path project)
|
;; (when (:java-source-path project)
|
||||||
(javac project))
|
;; (javac/javac project))
|
||||||
(if (seq (compilable-namespaces project))
|
(if (seq (compilable-namespaces project))
|
||||||
(if-let [namespaces (seq (stale-namespaces project))]
|
(if-let [namespaces (seq (stale-namespaces project))]
|
||||||
(binding [*skip-auto-compile* true]
|
(binding [*skip-auto-compile* true]
|
||||||
(try
|
(try
|
||||||
(if (zero? (eval-in-project project
|
(if (zero? (eval/eval-in-project project
|
||||||
`(doseq [namespace# '~namespaces]
|
`(doseq [namespace# '~namespaces]
|
||||||
(when-not ~*silently*
|
(when-not ~*silently*
|
||||||
(println "Compiling" namespace#))
|
(println "Compiling" namespace#))
|
||||||
(clojure.core/compile namespace#))))
|
(clojure.core/compile namespace#))))
|
||||||
(success "Compilation succeeded.")
|
(success "Compilation succeeded.")
|
||||||
(failure "Compilation failed."))
|
(failure "Compilation failed."))
|
||||||
(finally (clean-non-project-classes project))))
|
(finally (clean-non-project-classes project))))
|
||||||
|
|
38
todo.org
38
todo.org
|
@ -7,6 +7,44 @@ Leiningen TODOs
|
||||||
|
|
||||||
See also https://github.com/technomancy/leiningen/issues
|
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
|
* For 1.6.2
|
||||||
- [X] resources with eval-in-leiningen (#248)
|
- [X] resources with eval-in-leiningen (#248)
|
||||||
- [X] fix :omit-default-repositories wrt central (#211)
|
- [X] fix :omit-default-repositories wrt central (#211)
|
||||||
|
|
Loading…
Reference in a new issue