Created
January 12, 2011 03:03
-
-
Save rlm/775623 to your computer and use it in GitHub Desktop.
export_files.clj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns rlm.classpath-utils | |
(:require [clojure.contrib [duck-streams :as ds]]) | |
(:use [clojure.contrib java-utils])) | |
(defn classpath [] | |
(get-system-property "java.class.path")) | |
(defn add-to-classpath [file-name] | |
(wall-hack-method java.net.URLClassLoader | |
'addURL [java.net.URL] | |
(ClassLoader/getSystemClassLoader) | |
(.toURL (ds/file-str file-name)))) | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns coderloop.export-files | |
(:use clojure.java.io) | |
(:use [clojure.contrib [duck-streams :only [file-str]]]) | |
(:use [rlm | |
[classpath-utils :only [classpath]] | |
[shell-write :only [sw]]]) | |
(:require clojure.string) | |
(:import java.io.File) | |
) | |
(import '[org.apache.commons.io FileUtils]) | |
(defmulti source-location class) | |
(defmethod source-location clojure.lang.Var [sym] | |
(let [source? (:file (meta sym))] | |
(if source? | |
(.getResource (clojure.lang.RT/baseLoader) source?) | |
nil))) | |
(defmethod source-location java.lang.Class [sym] | |
(let [source? (.getCodeSource (.getProtectionDomain sym))] | |
(if source? | |
(.getLocation source?) | |
nil))) | |
(defn all-dependent-namespaces [namespace] | |
(set | |
(concat | |
[namespace] | |
(vals (ns-aliases namespace)) | |
(map #(.ns %) | |
(filter #(= (class %) clojure.lang.Var) | |
(concat | |
(vals (ns-map namespace)) | |
(vals (ns-refers namespace)) | |
)))))) | |
(defn deep-dependent-namespaces [namespace-set] | |
(let [new-namespaces (set (mapcat all-dependent-namespaces namespace-set))] | |
;;(println (count new-namespaces)) | |
(if (= new-namespaces namespace-set) | |
namespace-set | |
(recur new-namespaces)))) | |
(defn dependencies-url | |
"returns all of the files necessary to succesfully run the namespace." | |
[namespace] | |
(set | |
(remove nil? | |
(map source-location | |
(map second | |
(mapcat ns-map (deep-dependent-namespaces #{namespace}))))))) | |
(defn trans-print [x] (println x) x) | |
(defn dependencies-file [namespace] | |
(map file-str | |
(set | |
(map #(.replaceFirst % "file:" "") | |
(map #(if (.contains % ".jar!/") | |
(clojure.string/replace % #"\.jar.*" ".jar") | |
%) | |
(map #(.getFile %) (dependencies-url namespace))))))) | |
(defn classpath-files [] | |
(map file-str (clojure.string/split (classpath) #":"))) | |
;;Every file that comes back from dependencies-file is also on the classpath. | |
;;In order to recreate the right project structure, we need to copy the files | |
;;with the appropiate classpath nesting. | |
(defn bifurcate | |
"split a collection between f and not f" | |
[f coll] | |
(list | |
(filter f coll) | |
(filter (comp not f) coll))) | |
(defn jar? [#^java.io.File f] | |
(re-matches #".*\.jar$" (.getCanonicalPath f))) | |
(defn contains-file? [#^java.io.File parent #^java.io.File child] | |
(let [new-child (.getParentFile child)] | |
(cond (nil? new-child) false | |
(= new-child parent) true | |
true (recur parent new-child)))) | |
(defn destination [base-path-list #^java.io.File current-file #^java.io.File base-destination] | |
(let [base-path (last (filter #(contains-file? % current-file) base-path-list))] | |
(file-str | |
(.replaceFirst (.getCanonicalPath current-file) | |
(.getCanonicalPath base-path) | |
(.getCanonicalPath base-destination))))) | |
(defn export-dependencies [namespace #^java.io.File target] | |
(let [[jars sources] (bifurcate jar? (dependencies-file namespace)) | |
lib (file-str (str (.getCanonicalPath target) File/separatorChar "lib")) | |
src (file-str (str (.getCanonicalPath target) File/separatorChar "src"))] | |
(dorun (map #(FileUtils/copyFileToDirectory % lib) jars)) | |
(dorun (map #(FileUtils/copyFile % (destination (classpath-files) % src)) sources)))) | |
(defn run-script-text [namespace] | |
(str | |
"#!/bin/bash\n" | |
"java -Xmn500M -Xms2000M -Xmx2000M -server -cp ./lib/*:./src clojure.main " | |
"./src/" | |
(.replace (.replace (str *ns*) \. File/separatorChar) \- \_) | |
".clj " | |
" $@\n")) | |
(defn make-run-script [namespace base-dir name] | |
(let [w (clojure.java.io/writer | |
(str (.getCanonicalPath base-dir) File/separatorChar name))] | |
(.write w (run-script-text namespace)) | |
(.close w)) | |
(let [f (file-str (str (.getCanonicalPath base-dir) File/separatorChar name))] | |
(.setExecutable f true) | |
)) | |
(defn export-files [namespace base-dir name] | |
(export-dependencies namespace base-dir) | |
(make-run-script namespace base-dir name)) | |
(defn bzip-folder [#^java.io.File destination #^java.io.File directory] | |
(apply (partial sw "tar" "-cvjf" (.getCanonicalPath destination)) | |
(concat | |
(rest | |
(map #(.replaceFirst | |
% | |
(str (.getCanonicalPath directory) File/separatorChar ) "") | |
(map str (file-seq directory)))) | |
[:dir (.getCanonicalPath directory)]))) | |
(defn bzip-export-files [directory name] | |
(let [to (file-str "/home/r/coderloop/")] | |
(apply (partial sw "tar" "-cvjf" | |
(str (.getCanonicalPath to) File/separatorChar name "-clojure.tar.bz2")) | |
(concat | |
[name "lib" "src"] | |
[:dir (.getCanonicalPath directory)])))) | |
(def standard-base-directory (file-str "~/.clojure-exports/")) | |
(defn export-archive [namespace name] | |
(FileUtils/forceMkdir standard-base-directory) | |
(FileUtils/forceDelete standard-base-directory) | |
(FileUtils/forceMkdir standard-base-directory) | |
(let [new-dir (file-str (str | |
(.getCanonicalPath standard-base-directory) | |
(File/separatorChar) | |
name))] | |
(export-files namespace new-dir name) | |
(bzip-export-files new-dir name) | |
(FileUtils/copyFileToDirectory (file-str (str "~/coderloop/" name "-clojure.tar.bz2")) | |
(file-str "~/coderloop-test")) | |
)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns rlm.shell-write | |
(:use | |
[clojure.contrib | |
[duck-streams :only [file-str]] | |
command-line | |
str-utils | |
shell-out | |
]) | |
(:import (java.io File BufferedReader ByteArrayOutputStream InputStreamReader)) | |
(:import (org.apache.commons.exec PumpStreamHandler DefaultExecutor ExecuteWatchdog CommandLine))) | |
(defn sw | |
"same as sh but uses apache-commons to actually execute the process, | |
and prints output as soon as the subprocess returns output. Prints all | |
errors and normal ouput" | |
[& commands+args] | |
(let [[commands {:keys [dir]}] (split-with string? commands+args)] | |
(let | |
[ | |
parsed-commands (str (CommandLine/parse (apply str (interpose " " commands)))) | |
process (if dir | |
(.exec (Runtime/getRuntime) parsed-commands | |
(into-array String "") (file-str dir)) | |
(.exec (Runtime/getRuntime) parsed-commands))] | |
(let [reader | |
(BufferedReader. | |
(InputStreamReader. (.getInputStream process))) | |
error-reader | |
(BufferedReader. | |
(InputStreamReader. (.getErrorStream process)))] | |
;output from program | |
(loop [] | |
(let [line (.readLine reader )] | |
(if (not (nil? line)) | |
(do (println line) (recur)) nil))) | |
;errors from program | |
(let [err-str | |
(loop [errors ""] | |
(let [line (.readLine error-reader )] | |
(if (not (nil? line)) | |
(recur (str errors line "\n")) | |
errors)))] | |
(if (> (.length err-str) 0) | |
(do | |
(println "******************** Error Stream ********************") | |
(println err-str) | |
(println "******************************************************")))))))) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment