forked from technomancy/leiningen
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlancet.clj
More file actions
executable file
·135 lines (111 loc) · 4.25 KB
/
Copy pathlancet.clj
File metadata and controls
executable file
·135 lines (111 loc) · 4.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
(ns lancet
(:gen-class)
(:import (java.beans Introspector) (java.util.concurrent CountDownLatch)))
(defmulti coerce (fn [dest-class src-inst] [dest-class (class src-inst)]))
(defmethod coerce [java.io.File String] [_ str]
(java.io.File. str))
(defmethod coerce [Boolean/TYPE String] [_ str]
(contains? #{"on" "yes" "true"} (.toLowerCase str)))
(defmethod coerce :default [dest-cls obj] (cast dest-cls obj))
(defn env [val]
(System/getenv (name val)))
(defn- build-sh-args [args]
(concat (.split (first args) " +") (rest args)))
(def
#^{:doc "Dummy ant project to keep Ant tasks happy"}
ant-project
(let [proj (org.apache.tools.ant.Project.)
logger (org.apache.tools.ant.NoBannerLogger.)]
(doto logger
(.setMessageOutputLevel org.apache.tools.ant.Project/MSG_INFO)
(.setEmacsMode true)
(.setOutputPrintStream System/out)
(.setErrorPrintStream System/err))
(doto proj
(.init)
(.addBuildListener logger))))
(defn property-descriptor [inst prop-name]
(first
(filter #(= prop-name (.getName %))
(.getPropertyDescriptors
(Introspector/getBeanInfo (class inst))))))
(defn get-property-class [write-method]
(first (.getParameterTypes write-method)))
(defn set-property! [inst prop value]
(let [pd (property-descriptor inst prop)]
(when-not pd
(throw (Exception. (format "No such property %s." prop))))
(let [write-method (.getWriteMethod pd)
dest-class (get-property-class write-method)]
(.invoke write-method inst (into-array [(coerce dest-class value)])))))
(defn set-properties! [inst prop-map]
(doseq [[k v] prop-map] (set-property! inst (name k) v)))
(defn instantiate-task [project name props & filesets]
(let [task (.createTask project name)]
(when-not task
(throw (Exception. (format "No task named %s." name))))
(doto task
(.init)
(.setProject project)
(set-properties! props))
(doseq [fs filesets]
(.addFileset task fs))
task))
(defn runonce
"Create a function that will only run once. All other invocations
return the first calculated value. The function *can* have side effects
and calls to runonce *can* be composed. Deadlock is possible
if you have circular dependencies.
Returns a [has-run-predicate, reset-fn, once-fn]"
[function]
(let [sentinel (Object.)
result (atom sentinel)
reset-fn (fn [] (reset! result sentinel))
has-run-fn (fn [] (not= @result sentinel))]
[has-run-fn
reset-fn
(fn [& args]
(locking sentinel
(if (= @result sentinel)
(reset! result (function))
@result)))]))
(defmacro has-run? [f]
`((:has-run (meta (var ~f)))))
(defmacro reset [f]
`((:reset-fn (meta (var ~f)))))
(def targets (atom #{}))
(defmacro deftarget [sym doc & forms]
(swap! targets #(conj % sym))
(let [has-run (gensym "hr-") reset-fn (gensym "rf-")]
`(let [[~has-run ~reset-fn once-fn#] (runonce (fn [] ~@forms))]
(def ~(with-meta sym {:doc doc :has-run has-run :reset-fn reset-fn})
once-fn#))))
(defmacro define-ant-task [clj-name ant-name]
`(defn ~clj-name [& props#]
(let [task# (apply instantiate-task ant-project ~(name ant-name) props#)]
(.execute task#)
task#)))
(defmacro define-ant-type [clj-name ant-name]
`(defn ~clj-name [props#]
(let [bean# (new ~ant-name)]
(set-properties! bean# props#)
(when (property-descriptor bean# "project")
(set-property! bean# "project" ant-project))
bean#)))
(defn task-names [] (map symbol (seq (.. ant-project getTaskDefinitions keySet))))
(defn safe-ant-name [n]
(if (ns-resolve 'clojure.core n) (symbol (str "ant-" n)) n))
(defmacro define-all-ant-tasks []
`(do ~@(map (fn [n] `(define-ant-task ~n ~n)) (task-names))))
(defmacro define-all-ant-tasks []
`(do ~@(map (fn [n] `(define-ant-task ~(safe-ant-name n) ~n)) (task-names))))
(define-all-ant-tasks)
;; The version of ant that maven-ant-tasks requires doesn't have this class:
;; (define-ant-type files org.apache.tools.ant.types.resources.Files)
(define-ant-type fileset org.apache.tools.ant.types.FileSet)
(defn -main [& targs]
(load-file "build.clj")
(if targs
(doseq [targ (map symbol targs)]
(eval (list targ)))
(println "Available targets: " @targets)))