-
Notifications
You must be signed in to change notification settings - Fork 10
/
shared.clj
201 lines (162 loc) · 6.81 KB
/
shared.clj
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
(ns leiningen.polylith.cmd.shared
(:require [clojure.java.shell :as shell]
[clojure.string :as str]
[leiningen.polylith.file :as file]
[clojure.set :as set])
(:import (java.util.concurrent ExecutionException)))
(defn throw-polylith-exception
([message]
(throw (ExecutionException. message (Exception.)))))
(defn print-error-message [e]
(when-let [message (.getMessage e)]
(println message)))
(defn interface? [flag]
(contains? #{"i" "interface"} flag))
(defn +function? [flag]
(contains? #{"+f" "+function"} flag))
(defn component? [flag]
(contains? #{"c" "component"} flag))
(defn +component? [flag]
(contains? #{"+c" "+component"} flag))
(defn base? [flag]
(contains? #{"b" "base"} flag))
(defn system? [flag]
(contains? #{"s" "system"} flag))
(defn workspace? [flag]
(contains? #{"w" "workspace"} flag))
(defn has-args? [args & flags]
(not (empty? (set/intersection (set args) (set flags)))))
(defn src-dir-name [directory]
(str/replace directory #"-" "_"))
(defn entity-src-dir-name [directory]
(str/replace directory #"_" "-"))
(defn path->file [path]
(entity-src-dir-name (last (str/split (str path) #"/"))))
(defn full-name [top separator name]
(if (str/blank? top)
name
(if (= "" name)
(str top)
(str top separator name))))
(defn full-dir-name [top name]
(src-dir-name (full-name top "/" name)))
(defn src-root-dir [ws-path top-dir entity-dir entity]
(if (str/blank? top-dir)
(str ws-path "/" entity-dir "/" entity)
(str ws-path "/" entity-dir "/" entity "/" top-dir)))
(defn ->dependency [library lib-and-version]
"lib-and-version can either be a single library version number
or 'library (space) library-version'"
(let [[lib ver] (str/split lib-and-version #" ")]
(if ver
(str "[" lib " \"" ver "\"]")
(str "[" library " \"" lib "\"]"))))
(defn src-dirs [ws-path src-dir top-dir]
"Helper function for create-src-dirs!.
returns a list of full paths based 'ws-path', 'src-dir'
and the directories in 'top-dir', e.g.
if top-dir is 'a/b/c' then it returns something similar to:
['.../a' '.../a/b' '.../a/b/c']
where '.../' is 'ws-dir/src-dir/'."
(let [dirs (str/split top-dir #"/")
new-dirs (mapv #(str ws-path "/" src-dir "/" (str/join "/" (take % dirs)))
(range 1 (-> dirs count inc)))]
(if (zero? (count dirs))
[]
new-dirs)))
(defn create-src-dirs!
"This function assumes that the workspace is already created.
It creates 'ws-dir'/'src-dir' + all directories given in
the incoming 'top-dirs' parameter, beneath that directory."
([ws-path src-dir top-dirs]
(file/create-dir (str ws-path "/" src-dir))
(let [dirs (sort-by #(count (str/split % #"/"))
(set (mapcat #(src-dirs ws-path src-dir %) top-dirs)))]
(doseq [dir dirs]
(file/create-dir dir)))))
(defn relative-parent-path [dir]
(let [levels (+ 2 (count (str/split dir #"/")))]
(str/join (repeat levels "../"))))
(defn sh [& args]
(let [current-env (into {} (System/getenv))
new-env (dissoc current-env "CLASSPATH")
{:keys [exit out err]} (shell/with-sh-env new-env (apply shell/sh args))]
(if (= 0 exit)
out
(do
;; Print out the stack trace with the error message
(println out)
(throw-polylith-exception (str "Shell Err: " err " Exit code: " exit))))))
(defn interfaces-src-dir [top-dir]
(if (zero? (count top-dir))
"interfaces/src"
(str "interfaces/src/" top-dir)))
(defn libraries [path]
(let [content (first (file/read-file path))
index (ffirst
(filter #(= :dependencies (second %))
(map-indexed vector content)))]
(if index (nth content (inc index))
[])))
(defn all-interfaces [ws-path top-dir]
(set (file/directory-names (str ws-path "/" (interfaces-src-dir top-dir)))))
(defn all-components [ws-path]
(set (file/directory-names (str ws-path "/components"))))
(defn all-bases [ws-path]
(set (file/directory-names (str ws-path "/bases"))))
(defn all-systems [ws-path]
(set (file/directory-names (str ws-path "/systems"))))
(defn all-environments [ws-path]
(set (file/directory-names (str ws-path "/environments"))))
(defn libs [ws-path type entity]
(libraries (str ws-path (str type entity "/project.clj"))))
(defn all-libraries [ws-path]
(let [base-libs (mapcat #(libs ws-path "/bases/" %) (all-bases ws-path))
component-libs (mapcat #(libs ws-path "/components/" %) (all-components ws-path))
system-libs (mapcat #(libs ws-path "/systems/" %) (all-systems ws-path))
env-libs (mapcat #(libs ws-path "/environments/" %) (all-environments ws-path))]
(set (concat base-libs component-libs base-libs system-libs env-libs))))
(defn interface-of
([ws-path top-dir component]
(interface-of ws-path top-dir component (all-interfaces ws-path top-dir)))
([ws-path top-dir component interfaces]
(let [dir (str ws-path "/components/" component "/src/" (full-name top-dir "/" ""))
directories (file/directory-names dir)]
(first (filter #(contains? interfaces %) directories)))))
(defn ->interface-component [ws-path top-dir component interfaces]
[(interface-of ws-path top-dir component interfaces) component])
(defn interface->component [ws-path top-dir interfaces entities]
(into {} (filterv first
(map #(->interface-component ws-path top-dir % interfaces)
entities))))
(defn- ifc-comp->map [m [interface component]]
(if (contains? m interface)
(assoc m interface (conj (m interface) component))
(assoc m interface [component])))
(defn link->entity [ws-path path]
(try
(nth (str/split (subs (file/file->real-path path)
(count ws-path)) #"/")
2)
(catch Exception _)))
(defn used-entities
([ws-path top-dir type system-or-env]
(let [path (str ws-path "/" type "/" system-or-env "/src/" top-dir)]
(set (map #(link->entity ws-path %) (file/directories path)))))
([ws-path top-dir system-or-env]
(set (concat (used-entities ws-path top-dir "systems" system-or-env)
(used-entities ws-path top-dir "environments" system-or-env))))
([ws-path top-dir]
(let [sys-entities (mapcat #(used-entities ws-path top-dir "systems" %)
(all-systems ws-path))
env-entities (mapcat #(used-entities ws-path top-dir "environments" %)
(all-environments ws-path))]
(set (concat sys-entities env-entities)))))
(defn interface->components [ws-path top-dir used-components]
(let [interfaces (all-interfaces ws-path top-dir)]
(reduce ifc-comp->map {}
(map #(->interface-component ws-path top-dir % interfaces)
used-components))))
(defn ci? []
(or (System/getenv "CI")
(System/getProperty "CI")))