Merge branch 'master' of git://github.com/technomancy/leiningen

This commit is contained in:
Anthony Grimes 2011-11-20 16:39:30 -06:00
commit 40fdf2419f
7 changed files with 80 additions and 178 deletions

View file

@ -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"

View file

@ -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")))

View file

@ -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]

View file

@ -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"))

View file

@ -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))

View file

@ -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,14 +65,14 @@
(->> 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")))))
@ -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,13 +119,13 @@
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#))

View file

@ -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)