Merge remote branch 'mtyaka/windows-updates'

Conflicts:
	src/leiningen/jar.clj
	test/test_jar.clj
This commit is contained in:
Phil Hagelberg 2010-11-18 21:21:05 -08:00
commit c85aaf83a5
19 changed files with 210 additions and 90 deletions

View file

@ -69,10 +69,8 @@ set JLINE=jline.ConsoleRunner
:SKIP_JLINE
if "x%JAVA_CMD%" == "x" set JAVA_CMD="java"
%JAVA_CMD% -client %JAVA_OPTS% -Dleiningen.original.pwd="%ORIGINAL_PWD%" ^
-cp %CLASSPATH% %JLINE% clojure.main -e "(use 'leiningen.core)(-main)" NUL %*
goto EOF
set CLOJURE_JAR=%USERPROFILE%\.m2\repository\org\clojure\clojure\1.2.0\clojure-1.2.0.jar
goto RUN
:NO_LEIN_JAR
@ -170,4 +168,15 @@ goto :LOOK_AGAIN
set PARENT_PATH=%~f1
goto :EOF
:RUN
rem Need to disable delayed expansion because the %* variable
rem may contain bangs (as in test!).
setLocal DisableDelayedExpansion
%JAVA_CMD% -client %JAVA_OPTS% -Xbootclasspath/a:"%CLOJURE_JAR%" ^
-Dleiningen.original.pwd="%ORIGINAL_PWD%" ^
-cp %CLASSPATH% %JLINE% clojure.main -e "(use 'leiningen.core)(-main)" NUL %*
goto EOF
:EOF

View file

@ -1,6 +1,12 @@
#!/bin/sh
CLASSPATH="%s"
NULL_DEVICE=/dev/null
if [ "$OSTYPE" = "cygwin" ]; then
CLASSPATH=`cygpath -wp "$CLASSPATH"`
NULL_DEVICE=NUL
fi
java -cp "$CLASSPATH" $JAVA_OPTS \
clojure.main -e "(use '%s)(apply -main *command-line-args*)" /dev/null "$@"
clojure.main -e "(use '%s)(apply -main *command-line-args*)" $NULL_DEVICE "$@"

View file

@ -0,0 +1,6 @@
@echo off
set CLASSPATH="%s"
java -cp "%%CLASSPATH%%" %%JAVA_OPTS%% ^
clojure.main -e "(use '%s)(apply -main *command-line-args*)" NUL %%*

View file

@ -110,10 +110,25 @@
f
nil))))
(defn- get-jvm-args
[project]
(concat (.getInputArguments (ManagementFactory/getRuntimeMXBean))
(:jvm-opts project)))
;; Split this function out for better testability.
(defn- get-raw-input-args []
(.getInputArguments (ManagementFactory/getRuntimeMXBean)))
(defn- get-input-args
"Returns a vector of input arguments, accounting for a bug in RuntimeMXBean
that splits arguments which contain spaces."
[]
;; RuntimeMXBean.getInputArguments() is buggy when an input argument
;; contains spaces. For an input argument of -Dprop="hello world" it
;; returns ["-Dprop=hello", "world"]. Try to work around this bug.
(letfn [(join-broken-args [v arg] (if (= \- (first arg))
(conj v arg)
(conj (vec (butlast v))
(format "%s %s" (last v) arg))))]
(reduce join-broken-args [] (get-raw-input-args))))
(defn- get-jvm-args [project]
(concat (get-input-args) (:jvm-opts project)))
(defn get-readable-form [java project form init]
(let [cp (str (.getClasspath (.getCommandLine java)))
@ -170,6 +185,7 @@
(.setClasspath java (apply make-path (get-classpath project)))
(.setFailonerror java true)
(.setFork java true)
(.setDir java (file (:root project)))
(doseq [arg (get-jvm-args project)]
(when-not (re-matches #"^-Xbootclasspath.+" arg)
(.setValue (.createJvmarg java) arg)))
@ -218,6 +234,7 @@ those given as command-line arguments."
(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

View file

@ -21,37 +21,47 @@
;; any namespace due to load-file; we can't just create a var with
;; def or we would not have access to it once load-file returned.
`(let [m# (apply hash-map ~(cons 'list (unquote-project args)))
root# ~(.getParent (File. *file*))]
root# ~(.getParent (File. *file*))
normalize-path# (fn [p#] (when p# (.getPath (File. p#))))]
(alter-var-root #'project
(fn [_#] (assoc m#
:name ~(name project-name)
:group ~(or (namespace project-name)
(name project-name))
:version ~version
:compile-path (or (:compile-path m#)
(str root# "/classes"))
:source-path (or (:source-path m#)
(str root# "/src"))
:library-path (or (:library-path m#)
(str root# "/lib"))
:test-path (or (:test-path m#)
(str root# "/test"))
:resources-path (or (:resources-path m#)
(str root# "/resources"))
:compile-path (normalize-path#
(or (:compile-path m#)
(str root# "/classes")))
:source-path (normalize-path#
(or (:source-path m#)
(str root# "/src")))
:library-path (normalize-path#
(or (:library-path m#)
(str root# "/lib")))
:test-path (normalize-path#
(or (:test-path m#)
(str root# "/test")))
:resources-path (normalize-path#
(or (:resources-path m#)
(str root# "/resources")))
:dev-resources-path
(or (:dev-resources-path m#)
(:test-resources-path m#)
(str root# "/test-resources"))
(normalize-path#
(or (:dev-resources-path m#)
(:test-resources-path m#)
(str root# "/test-resources")))
;; TODO: remove in 2.0
:test-resources-path
(or (:dev-resources-path m#)
(:test-resources-path m#)
(str root# "/test-resources"))
:target-dir (or (:target-dir m#) (:jar-dir m#)
root#)
(normalize-path#
(or (:dev-resources-path m#)
(:test-resources-path m#)
(str root# "/test-resources")))
:target-dir (normalize-path#
(or (:target-dir m#) (:jar-dir m#)
root#))
;; TODO: remove in 2.0
:jar-dir (or (:target-dir m#) (:jar-dir m#)
root#)
:jar-dir (normalize-path#
(or (:target-dir m#) (:jar-dir m#)
root#))
:root root#)))
(when (:test-resources-path m#)
(println (str "WARNING: :test-resources-path is deprecated; use "

View file

@ -6,7 +6,7 @@
[leiningen.util.maven :only [container make-model make-remote-artifact
make-remote-repo make-local-repo
make-artifact add-metadata]]
[leiningen.util.file :only [delete-file-recursively]]
[leiningen.util.file :only [tmp-dir delete-file-recursively]]
[leiningen.pom :only [pom]]
[clojure.java.io :only [file copy]])
(:import [java.util.jar JarFile]
@ -16,14 +16,16 @@
(defn bin-path []
(doto (file (home-dir) "bin") .mkdirs))
(defn install-shell-wrapper [jarfile]
(defn install-shell-wrappers [jarfile]
(when-let [bin-name ((manifest-map (.getManifest jarfile))
"Leiningen-shell-wrapper")]
(let [bin-file (file (bin-path) (last (.split bin-name "/")))]
(.mkdirs (.getParentFile bin-file))
(println "Installing shell wrapper to" (.getAbsolutePath bin-file))
(copy (.getInputStream jarfile (.getEntry jarfile bin-name)) bin-file)
(.setExecutable bin-file true))))
(doseq [entry-path [bin-name (format "%s.bat" bin-name)]]
(let [bin-file (file (bin-path) (last (.split entry-path "/")))]
(.mkdirs (.getParentFile bin-file))
(when-let [zip-entry (.getEntry jarfile entry-path)]
(println "Installing shell wrapper to" (.getAbsolutePath bin-file))
(copy (.getInputStream jarfile zip-entry) bin-file)
(.setExecutable bin-file true))))))
(defn standalone-download [name group version]
(.resolveAlways (.lookup container ArtifactResolver/ROLE)
@ -45,15 +47,15 @@ from a remote repository. May place shell wrappers in ~/.lein/bin."
;; generated and installed in local repo
(if (not= "pom" (.getPackaging model))
(add-metadata artifact (file (pom project))))
(install-shell-wrapper (JarFile. jarfile))
(install-shell-wrappers (JarFile. jarfile))
(.install installer jarfile artifact local-repo)))
([project-name version]
(let [[name group] ((juxt name namespace) (symbol project-name))
_ (standalone-download name (or group name) version)
temp-project (format "/tmp/lein-%s" (java.util.UUID/randomUUID))
temp-project (format "%s/lein-%s" tmp-dir (java.util.UUID/randomUUID))
jarfile (-> (local-repo-path name (or group name) version)
(.replace "$HOME" (System/getenv "HOME")))]
(install-shell-wrapper (JarFile. jarfile))
(.replace "$HOME" (System/getProperty "user.home")))]
(install-shell-wrappers (JarFile. jarfile))
;; TODO: use lancet/unjar?
(try (extract-jar (file jarfile) temp-project)
(binding [*ns* (the-ns 'leiningen.core)

View file

@ -1,10 +1,10 @@
(ns leiningen.jar
"Create a jar containing the compiled code and original source."
(:require [leiningen.compile :as compile]
[clojure.string :as string])
[clojure.string :as string]
[lancet])
(:use [leiningen.pom :only [make-pom make-pom-properties]]
[leiningen.deps :only [deps]]
[lancet :only [ant-project]]
[clojure.java.io :only [copy file]])
(:import [java.util.jar Manifest JarEntry JarOutputStream]
[java.util.regex Pattern]
@ -12,44 +12,71 @@
[java.io BufferedOutputStream FileOutputStream
ByteArrayInputStream]))
(def bin-template (-> (.getContextClassLoader (Thread/currentThread))
(.getResourceAsStream "script-template")
(slurp)))
(defn- read-resource [resource-name]
(-> (.getContextClassLoader (Thread/currentThread))
(.getResourceAsStream resource-name)
(slurp)))
(defn- read-bin-template [system]
(case system
:unix (read-resource "script-template")
:windows (read-resource "script-template.bat")))
(defn unix-path [path]
(.replace path "\\" "/"))
(defn windows-path [path]
(.replace path "/" "\\"))
(defn local-repo-path
([group name version]
(local-repo-path {:group group :name name :version version}))
([{:keys [group name version]}]
(format "$HOME/.m2/repository/%s/%s/%s/%s-%s.jar"
(.replaceAll group "\\." "/") name version name version)))
(unix-path (format
"$HOME/.m2/repository/%s/%s/%s/%s-%s.jar"
(.replace group "." "/") name version name version))))
(defn- script-classpath-for [project deps-fileset]
(string/join ":" (conj (for [dep (when (:dependencies project)
(-> deps-fileset
(.getDirectoryScanner ant-project)
(.getIncludedFiles)))]
(format "$HOME/.m2/repository/%s" dep))
(local-repo-path project))))
(defn- script-classpath-for [project deps-fileset system]
(let [deps (when deps-fileset
(-> deps-fileset
(.getDirectoryScanner lancet/ant-project)
(.getIncludedFiles)))
unix-paths (conj (for [dep deps]
(unix-path (format "$HOME/.m2/repository/%s" dep)))
(local-repo-path project))]
(case system
:unix (string/join ":" unix-paths)
:windows (string/join ";" (for [path unix-paths]
(windows-path
(.replace path "$HOME"
"%USERPROFILE%")))))))
(defn- shell-wrapper-name [project]
(or (:bin (:shell-wrapper project)
(format "bin/%s" (:name project)))))
(get-in project [:shell-wrapper :bin]
(format "bin/%s" (:name project))))
(defn- shell-wrapper-contents [project bin-name main deps-fileset]
(let [bin-file (file bin-name)]
(defn- shell-wrapper-contents [project bin-name main deps-fileset system]
(let [file-name (case system
:unix bin-name
:windows (format "%s.bat" bin-name))
bin-file (file file-name)]
(format (if (.exists bin-file)
(slurp bin-file)
bin-template)
(script-classpath-for project deps-fileset) main)))
(read-bin-template system))
(script-classpath-for project deps-fileset system) main)))
(defn- shell-wrapper-filespecs [project deps-fileset]
(when (:shell-wrapper project)
(let [main (or (:main (:shell-wrapper project)) (:main project))
bin-name (shell-wrapper-name project)
bin (shell-wrapper-contents project bin-name main deps-fileset)]
read-bin #(shell-wrapper-contents
project bin-name main deps-fileset %)]
[{:type :bytes
:path bin-name
:bytes (.getBytes bin)}])))
:bytes (.getBytes (read-bin :unix))}
{:type :bytes
:path (format "%s.bat" bin-name)
:bytes (.getBytes (read-bin :windows))}])))
(def default-manifest
{"Created-By" (str "Leiningen " (System/getenv "LEIN_VERSION"))
@ -73,9 +100,6 @@
(let [attrs (.getMainAttributes manifest)]
(zipmap (map str (keys attrs)) (vals attrs))))
(defn unix-path [path]
(.replaceAll path "\\\\" "/"))
(defn skip-file? [file relative-path patterns]
(or (.isDirectory file)
(re-find #"^\.?#" (.getName file))

View file

@ -1,11 +1,13 @@
(ns leiningen.plugin
(:use [leiningen.core :only (home-dir
read-project)]
read-project
abort)]
[leiningen.uberjar :only (write-components)]
[leiningen.deps :only (deps)]
[leiningen.jar :only (local-repo-path
extract-jar
get-default-uberjar-name)]
[leiningen.util.file :only (tmp-dir)]
[clojure.java.io :only (file)])
(:require [leiningen.install]
[leiningen.help])
@ -30,9 +32,9 @@ Syntax: lein plugin install [GROUP/]ARTIFACT-ID VERSION
[project-name version]
(leiningen.install/install project-name version)
(let [[name group] (extract-name-and-group project-name)
temp-project (format "/tmp/lein-%s" (java.util.UUID/randomUUID))
temp-project (format "%s/lein-%s" tmp-dir (java.util.UUID/randomUUID))
jarfile (-> (local-repo-path name (or group name) version)
(.replace "$HOME" (System/getenv "HOME")))
(.replace "$HOME" (System/getProperty "user.home")))
_ (extract-jar (file jarfile) temp-project)
project (read-project (format "%s/project.clj" temp-project))
standalone-filename (plugin-standalone-filename group name version)]
@ -50,9 +52,15 @@ Syntax: lein plugin install [GROUP/]ARTIFACT-ID VERSION
"Delete the plugin jarfile
Syntax: lein plugin uninstall [GROUP/]ARTIFACT-ID VERSION"
[project-name version]
(let [[name group] (extract-name-and-group project-name)]
(.delete (file plugins-path
(plugin-standalone-filename group name version)))))
(let [[name group] (extract-name-and-group project-name)
jarfile (file plugins-path
(plugin-standalone-filename group name version))]
(if (.exists jarfile)
(if (.delete jarfile)
(println (format "Successfully uninstalled %s %s." project-name version))
(abort (format "Failed to delete \"%s\"." (.getAbsolutePath jarfile))))
(abort (format "Plugin \"%s %s\" doesn't appear to be installed."
project-name version)))))
(defn ^{:doc "Manage user-level plugins."
:help-arglists '([subtask project-name version])

View file

@ -1,6 +1,8 @@
(ns leiningen.util.file
(:use [clojure.java.io :only [file delete-file]]))
(def tmp-dir (System/getProperty "java.io.tmpdir"))
;; grumble, grumble; why didn't this make it into clojure.java.io?
(defn delete-file-recursively
"Delete file f. If it's a directory, recursively delete all its contents.

View file

@ -1,7 +1,8 @@
(ns leiningen.util.maven
(:use [leiningen.core :only [repositories-for abort]]
[clojure.java.io :only [file reader]])
(:import [org.apache.maven.model Build Model Parent Dependency
(:import [java.io File]
[org.apache.maven.model Build Model Parent Dependency
Exclusion Repository Scm License MailingList Resource]
[org.apache.maven.project.artifact ProjectArtifactMetadata]
[org.apache.maven.settings MavenSettingsBuilder]
@ -195,7 +196,7 @@ to exclude from transitive dependencies."
(defn- relative-path
[project path-key]
(.replace (path-key project) (str (:root project) "/") ""))
(.replace (path-key project) (str (:root project) File/separator) ""))
(defmacro ^{:private true} add-a-resource [build method resource-path]
`(let [resource# (Resource.)]

View file

@ -41,3 +41,9 @@
(is (some (partial re-find r) classes) (format "missing %s" r))))
(is (not (.exists (file "test_projects" "sample"
"classes" "sample2" "core.class")))))
(deftest test-spaces-in-project-path
(binding [leiningen.compile/get-raw-input-args
(fn [] ["-Dleiningen.original.pwd=/path/with" "spaces/got-broken"])]
(is (zero? (eval-in-project (make-project "test_projects/sample")
`(System/exit 0))))))

View file

@ -9,17 +9,28 @@
(def m2-dir (file local-repo "nomnomnom" "nomnomnom" "0.5.0-SNAPSHOT"))
(def unix-shell-wrapper (file (home-dir) "bin" "nom"))
(def windows-shell-wrapper (file (home-dir) "bin" "nom.bat"))
(defonce test-project (read-project "test_projects/sample/project.clj"))
(defn delete-shell-wrappers []
(.delete unix-shell-wrapper)
(.delete windows-shell-wrapper))
(deftest test-install
(delete-file-recursively m2-dir true)
(delete-shell-wrappers)
(install test-project)
(is (not (empty? (.listFiles m2-dir)))))
(is (not (empty? (.listFiles m2-dir))))
(is (.exists unix-shell-wrapper))
(is (.exists windows-shell-wrapper)))
(def jdom-dir (file local-repo "jdom" "jdom" "1.0"))
(deftest test-standalone-install
(delete-file-recursively jdom-dir true)
(delete-shell-wrappers)
(install "nomnomnom" "0.5.0-SNAPSHOT")
(is (not (empty? (.listFiles jdom-dir))))
(is (.exists (file (home-dir) "bin" "nom"))))
(is (.exists unix-shell-wrapper)))

View file

@ -18,16 +18,24 @@
(deftest test-jar
(let [jar-file (JarFile. (jar sample-project))
manifest (manifest-map (.getManifest jar-file))
bin (slurp (.getInputStream jar-file (.getEntry jar-file "bin/nom")))]
bin (slurp (.getInputStream jar-file (.getEntry jar-file "bin/nom")))
bat (slurp (.getInputStream jar-file (.getEntry jar-file
"bin/nom.bat")))]
(is (= "bin/nom" (manifest "Leiningen-shell-wrapper")))
(is (re-find #"org/clojure/clojure/1.1.0-master-SNAPSHOT/" bin))
(is (re-find #"org/clojure/clojure/1\.1\.0-master-SNAPSHOT/" bin))
(is (re-find #"org\\clojure\\clojure\\1\.1\.0-master-SNAPSHOT" bat))
(is (re-find #"use 'nom\.nom\.nom\)\(apply -main .command-line-args." bin))
(is (re-find #"\$HOME/\.m2/repository/rome/rome/0.9/rome-0\.9\.jar" bin))))
(is (re-find #"use 'nom\.nom\.nom\)\(apply -main .command-line-args." bat))
(is (re-find #"\$HOME/\.m2/repository/rome/rome/0\.9/rome-0\.9\.jar" bin))
(is (re-find
#"%USERPROFILE%\\\.m2\\repository\\rome\\rome\\0\.9\\rome-0\.9\.jar"
bat))))
(deftest test-no-bin-jar
(let [jar-file (JarFile. (jar (dissoc sample-project :shell-wrapper)))
manifest (manifest-map (.getManifest jar-file))]
(is (nil? (.getEntry jar-file "bin/nom")))
(is (nil? (.getEntry jar-file "bin/nom.bat")))
(is (nil? (manifest "Leiningen-shell-wrapper")))))
(def sample-failing-project
@ -54,9 +62,12 @@
(let [jar-file (JarFile. (jar tricky-name))
manifest (manifest-map (.getManifest jar-file))
bin (slurp (.getInputStream
jar-file (.getEntry jar-file "bin/tricky-name")))]
jar-file (.getEntry jar-file "bin/tricky-name")))
bat (slurp (.getInputStream
jar-file (.getEntry jar-file "bin/tricky-name.bat")))]
(is (= "bin/tricky-name" (manifest "Leiningen-shell-wrapper")))
(is (re-find #"org/domain/tricky-name/1.0/tricky-name-1\.0\.jar" bin))))
(is (re-find #"org/domain/tricky-name/1\.0/tricky-name-1\.0\.jar" bin))
(is (re-find #"\\domain\\tricky-name\\1\.0\\tricky-name-1\.0\.jar" bat))))
(deftest test-no-deps-jar
(let [jar-file (jar (dissoc sample-project :dependencies :dev-dependencies))]

View file

@ -2,9 +2,10 @@
(:use [clojure.test]
[clojure.java.io :only [delete-file]]
[leiningen.core :only [read-project]]
[leiningen.run]))
[leiningen.run]
[leiningen.util.file :only [tmp-dir]]))
(def out-file "/tmp/lein-test")
(def out-file (format "%s/lein-test" tmp-dir))
(def project (binding [*ns* (find-ns 'leiningen.core)]
(read-project "test_projects/tricky-name/project.clj")))

View file

@ -1,12 +1,13 @@
(ns test-test
(:refer-clojure :exclude [test])
(:use [leiningen.test]
[leiningen.util.file :only [tmp-dir]]
[leiningen.core :only [read-project]] :reload)
(:use [clojure.test]))
(use-fixtures :each
(fn [f]
(.delete (java.io.File. "/tmp/lein-test-ran"))
(.delete (java.io.File. tmp-dir "lein-test-ran"))
(f)))
(def project (binding [*ns* (find-ns 'leiningen.core)]
@ -14,7 +15,8 @@
(defn ran? [& expected]
(= (set expected)
(set (map read-string (.split (slurp "/tmp/lein-test-ran") "\n")))))
(set (map read-string (.split (slurp (format "%s/lein-test-ran" tmp-dir))
"\n")))))
(deftest test-project-selectors
(is (= [:default :integration :int2 :no-custom]

View file

@ -3,8 +3,10 @@
[clojure.java.io]))
(defn record-ran [t]
(with-open [w (writer "/tmp/lein-test-ran" :append true)]
(.write w (str t "\n"))))
(let [file-name (format "%s/lein-test-ran"
(System/getProperty "java.io.tmpdir"))]
(with-open [w (writer file-name :append true)]
(.write w (str t "\n")))))
(deftest ^{:integration true} integration-test
(record-ran :integration)

View file

@ -1,4 +1,4 @@
(ns org.domain.tricky-name.brunch)
(defn -main [& args]
(spit "/tmp/lein-test" "BRUNCH"))
(spit (format "%s/lein-test" (System/getProperty "java.io.tmpdir")) "BRUNCH"))

View file

@ -2,5 +2,6 @@
(defn -main [& args]
(when-not (empty? args)
(spit "/tmp/lein-test" (str "nom:" (first args)))
(spit (format "%s/lein-test" (System/getProperty "java.io.tmpdir"))
(str "nom:" (first args)))
(recur (rest args))))

View file

@ -1,4 +1,5 @@
(ns org.domain.tricky-name.munch)
(defn -main [& args]
(spit "/tmp/lein-test" (pr-str :munched args)))
(spit (format "%s/lein-test" (System/getProperty "java.io.tmpdir"))
(pr-str :munched args)))