Add support for windows .bat wrappers.

This commit is contained in:
Matjaz Gregoric 2010-11-16 23:27:15 +01:00
parent 09e4881bd0
commit 0a6ec18e0d
5 changed files with 86 additions and 33 deletions

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

@ -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,7 +47,7 @@ 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))
@ -53,7 +55,7 @@ from a remote repository. May place shell wrappers in ~/.lein/bin."
temp-project (format "/tmp/lein-%s" (java.util.UUID/randomUUID))
jarfile (-> (local-repo-path name (or group name) version)
(.replace "$HOME" (System/getProperty "user.home")))]
(install-shell-wrapper (JarFile. jarfile))
(install-shell-wrappers (JarFile. jarfile))
;; TODO: use lancet/unjar?
(try (extract-jar (file jarfile) temp-project)
(binding [*ns* (the-ns 'leiningen.core)

View file

@ -11,12 +11,21 @@
[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]
(.replaceAll path "\\\\" "/"))
(.replace path "\\" "/"))
(defn windows-path [path]
(.replace path "/" "\\"))
(defn local-repo-path
([group name version]
@ -24,34 +33,48 @@
([{:keys [group name version]}]
(unix-path (format
"$HOME/.m2/repository/%s/%s/%s/%s-%s.jar"
(.replaceAll group "\\." "/") name version name version))))
(.replace group "." "/") name version name version))))
(defn- script-classpath-for [project deps-fileset]
(string/join ":" (conj (for [dep (-> deps-fileset
(.getDirectoryScanner lancet/ant-project)
(.getIncludedFiles))]
(defn- script-classpath-for [project deps-fileset system]
(let [deps (-> 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))))
(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"))

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,6 +62,9 @@
(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 #"org\\domain\\tricky-name\\1\.0\\tricky-name-1\.0\.jar" bat))))