[#1110] Load tasks and deps from other bb.edn file (#1117)

Co-authored-by: Bob <highpressurecarsalesman@gmail.com>
This commit is contained in:
Michiel Borkent 2021-12-26 17:26:35 +01:00 committed by GitHub
parent 93fb4379ff
commit fb7f984389
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 333 additions and 304 deletions

View file

@ -58,8 +58,8 @@ jobs:
java -jar $jar script/reflection.clj java -jar $jar script/reflection.clj
reflection="babashka-$VERSION-reflection.json" reflection="babashka-$VERSION-reflection.json"
BABASHKA_EDN=".build/bb.edn" java -jar "$jar" release-artifact "$jar" java -jar "$jar" --config .build/bb.edn --deps-root . release-artifact "$jar"
BABASHKA_EDN=".build/bb.edn" java -jar "$jar" release-artifact "$reflection" java -jar "$jar" --config .build/bb.edn --deps-root . release-artifact "$reflection"
- store_artifacts: - store_artifacts:
path: /tmp/release path: /tmp/release
destination: release destination: release

View file

@ -24,7 +24,7 @@ tar zcvf "$archive" bb # bbk
cd - cd -
BABASHKA_EDN=".build/bb.edn" ./bb release-artifact "/tmp/release/$archive" ./bb --config .build/bb.edn --deps-root . release-artifact "/tmp/release/$archive"
## cleanup ## cleanup

View file

@ -0,0 +1 @@
{:lint-as {babashka.fs/with-temp-dir clojure.core/let}}

2
.dir-locals.el Normal file
View file

@ -0,0 +1,2 @@
((clojure-mode
(cider-clojure-cli-aliases . "test")))

View file

@ -62,11 +62,7 @@ build_script:
jar -cMf %zip% bb.exe jar -cMf %zip% bb.exe
set BABASHKA_EDN=.build/bb.edn bb --config .build/bb.edn --deps-root . release-artifact %zip%
bb release-artifact %zip%
set BABASHKA_EDN=
set BABASHKA_CLASSPATH= set BABASHKA_CLASSPATH=

View file

@ -4,8 +4,4 @@ set EDN=lib_tests.edn
.\bb -f script/lib_tests/bb_edn_from_deps.clj %EDN% .\bb -f script/lib_tests/bb_edn_from_deps.clj %EDN%
set BABASHKA_EDN=%EDN% %BB_CMD% --config %EDN% --deps-root . -f test-resources/lib_tests/babashka/run_all_libtests.clj %*
%BB_CMD% -f test-resources/lib_tests/babashka/run_all_libtests.clj %*
set BABASHKA_EDN=

View file

@ -1,6 +1,8 @@
(ns babashka.impl.deps (ns babashka.impl.deps
(:require [babashka.deps :as bdeps] (:require [babashka.deps :as bdeps]
[babashka.fs :as fs]
[babashka.impl.classpath :as cp] [babashka.impl.classpath :as cp]
[babashka.impl.common :refer [bb-edn]]
[borkdude.deps :as deps] [borkdude.deps :as deps]
[clojure.string :as str] [clojure.string :as str]
[sci.core :as sci])) [sci.core :as sci]))
@ -58,8 +60,19 @@
([deps-map] (add-deps deps-map nil)) ([deps-map] (add-deps deps-map nil))
([deps-map {:keys [:aliases :env :extra-env :force]}] ([deps-map {:keys [:aliases :env :extra-env :force]}]
(when-let [paths (:paths deps-map)] (when-let [paths (:paths deps-map)]
(cp/add-classpath (str/join cp/path-sep paths))) (let [paths (let [deps-root (:deps-root @bb-edn)
(when-let [deps-map (not-empty (dissoc deps-map :paths :tasks :raw :min-bb-version))] deps-root (fs/absolutize deps-root)
;; cwd (fs/absolutize ".")
;; rel (fs/relativize cwd f)
paths (mapv #(str (fs/file deps-root %)) paths)]
paths)]
(cp/add-classpath (str/join cp/path-sep paths))))
(when-let [deps-map (not-empty (dissoc deps-map
;; paths are added manually above
:paths
;; extra-paths are transformed to :deps in task handling
:extra-paths
:tasks :raw :min-bb-version))]
(binding [*print-namespace-maps* false] (binding [*print-namespace-maps* false]
(let [deps-map (assoc-in deps-map [:aliases :org.babashka/defaults] (let [deps-map (assoc-in deps-map [:aliases :org.babashka/defaults]
{:replace-paths [] ;; babashka sets paths manually {:replace-paths [] ;; babashka sets paths manually

View file

@ -229,8 +229,7 @@
(defn format-task [init extra-paths extra-deps requires prog] (defn format-task [init extra-paths extra-deps requires prog]
(format " (format "
%s ;; extra-paths %s ;; deps
%s ;; extra-deps
(ns %s %s) (ns %s %s)
(require '[babashka.tasks]) (require '[babashka.tasks])
@ -251,12 +250,12 @@
%s %s
" "
(if (seq extra-paths) (let [deps (cond-> {}
(format "(babashka.classpath/add-classpath \"%s\")" (str/join cp/path-sep extra-paths)) (seq extra-deps) (assoc :deps extra-deps)
"") (seq extra-paths) (assoc :paths extra-paths))]
(if (seq extra-deps) (if (seq deps)
(format "(babashka.deps/add-deps '%s)" (pr-str {:deps extra-deps})) (format "(babashka.deps/add-deps '%s)" (pr-str deps))
"") ""))
@rand-ns @rand-ns
(if (seq requires) (if (seq requires)
(format "(:require %s)" (str/join " " requires)) (format "(:require %s)" (str/join " " requires))
@ -271,13 +270,13 @@
depends (:depends task)] depends (:depends task)]
(when (contains? processing task-name) (when (contains? processing task-name)
(throw (ex-info (str "Cyclic task: " task-name) {}))) (throw (ex-info (str "Cyclic task: " task-name) {})))
(loop [deps (seq depends)] (let [deps (seq depends)
(let [deps (remove #(contains? @processed %) deps) deps (remove #(contains? @processed %) deps)
order (vec (mapcat #(target-order tasks % processed (conj processing task-name)) deps))] order (vec (mapcat #(target-order tasks % processed (conj processing task-name)) deps))]
(if-not (contains? @processed task-name) (if-not (contains? @processed task-name)
(do (vswap! processed conj task-name) (do (vswap! processed conj task-name)
(conj order task-name)) (conj order task-name))
order)))))) order)))))
#_(defn tasks->dependees [task-names tasks] #_(defn tasks->dependees [task-names tasks]
(let [tasks->depends (zipmap task-names (map #(:depends (get tasks %)) task-names))] (let [tasks->depends (zipmap task-names (map #(:depends (get tasks %)) task-names))]

View file

@ -137,6 +137,8 @@ Global opts:
--debug Print debug information and internal stacktrace in case of exception. --debug Print debug information and internal stacktrace in case of exception.
--force Passes -Sforce to deps.clj, forcing recalculation of the classpath. --force Passes -Sforce to deps.clj, forcing recalculation of the classpath.
--init <file> Load file after any preloads and prior to evaluation/subcommands. --init <file> Load file after any preloads and prior to evaluation/subcommands.
--config <file> Replacing bb.edn with file. Relative paths are resolved relative to file.
--deps-root <dir> Treat dir as root of relative paths in config.
Help: Help:
@ -632,21 +634,27 @@ Use bb run --help to show this help output.
(if options (if options
(case (first options) (case (first options)
("--classpath" "-cp") (recur (nnext options) (assoc opts-map :classpath (second options))) ("--classpath" "-cp") (recur (nnext options) (assoc opts-map :classpath (second options)))
("--debug" ("--debug"
"--verbose" ;; renamed to --debug "--verbose")
) (recur (next options) (assoc opts-map :debug true)) ;; renamed to --debug
(recur (next options) (assoc opts-map :debug true))
("--init") ("--init")
(recur (nnext options) (assoc opts-map :init (second options))) (recur (nnext options) (assoc opts-map :init (second options)))
("--config")
(recur (nnext options) (assoc opts-map :config (second options)))
("--deps-root")
(recur (nnext options) (assoc opts-map :deps-root (second options)))
[options opts-map]) [options opts-map])
[options opts-map]))) [options opts-map])))
(defn parse-opts (defn parse-opts
([options] (parse-opts options nil)) ([options] (parse-opts options nil))
([options opts-map] ([options opts-map]
(let [[options opts-map] (if opts-map (let [opt (first options)
[options opts-map]
(parse-global-opts options))
opt (first options)
tasks (into #{} (map str) (keys (:tasks @common/bb-edn)))] tasks (into #{} (map str) (keys (:tasks @common/bb-edn)))]
(if-not opt opts-map (if-not opt opts-map
;; FILE > TASK > SUBCOMMAND ;; FILE > TASK > SUBCOMMAND
@ -743,228 +751,231 @@ Use bb run --help to show this help output.
(binding [*out* *err*] (binding [*out* *err*]
(println "[babashka] WARNING: clojure.core.specs.alpha is removed from the classpath, unless you explicitly add the dependency.")) (println "[babashka] WARNING: clojure.core.specs.alpha is removed from the classpath, unless you explicitly add the dependency."))
nil))) nil)))
main (if (and jar (not main)) main (if (and jar (not main))
(when-let [res (cp/getResource (when-let [res (cp/getResource
(cp/loader jar) (cp/loader jar)
["META-INF/MANIFEST.MF"] {:url? true})] ["META-INF/MANIFEST.MF"] {:url? true})]
(cp/main-ns res)) (cp/main-ns res))
main) main)
;; TODO: pull more of these values to compile time ;; TODO: pull more of these values to compile time
opts {:aliases aliases opts {:aliases aliases
:namespaces (-> namespaces :namespaces (-> namespaces
(assoc 'clojure.core (assoc 'clojure.core
(assoc core-extras (assoc core-extras
'load-file (sci-namespaces/core-var 'load-file load-file*)))) 'load-file (sci-namespaces/core-var 'load-file load-file*))))
:env env :env env
:features #{:bb :clj} :features #{:bb :clj}
:classes classes/class-map :classes classes/class-map
:imports classes/imports :imports classes/imports
:load-fn load-fn :load-fn load-fn
:uberscript uberscript :uberscript uberscript
;; :readers core/data-readers ;; :readers core/data-readers
:reify-fn reify-fn :reify-fn reify-fn
:proxy-fn proxy-fn} :proxy-fn proxy-fn}
opts (addons/future opts) opts (addons/future opts)
sci-ctx (sci/init opts) sci-ctx (sci/init opts)
_ (vreset! common/ctx sci-ctx) _ (vreset! common/ctx sci-ctx)
preloads (some-> (System/getenv "BABASHKA_PRELOADS") (str/trim)) preloads (some-> (System/getenv "BABASHKA_PRELOADS") (str/trim))
[expressions exit-code] [expressions exit-code]
(cond expressions [expressions nil] (cond expressions [expressions nil]
main main
(let [sym (symbol main) (let [sym (symbol main)
ns? (namespace sym) ns? (namespace sym)
ns (or ns? sym) ns (or ns? sym)
var-name (if ns? var-name (if ns?
(name sym) (name sym)
"-main")] "-main")]
[[(format "(ns user (:require [%1$s])) (apply %1$s/%2$s *command-line-args*)" [[(format "(ns user (:require [%1$s])) (apply %1$s/%2$s *command-line-args*)"
ns var-name)] nil]) ns var-name)] nil])
run (if (:run-help cli-opts) run (if (:run-help cli-opts)
[(print-run-help) 0] [(print-run-help) 0]
(do (do
(System/setProperty "babashka.task" (str run)) (System/setProperty "babashka.task" (str run))
(tasks/assemble-task run (tasks/assemble-task run
(:parallel-tasks cli-opts)))) (:parallel-tasks cli-opts))))
file (try [[(read-file file)] nil] file (try [[(read-file file)] nil]
(catch Exception e (catch Exception e
(error-handler e {:expression expressions (error-handler e {:expression expressions
:debug debug :debug debug
:preloads preloads :preloads preloads
:init init :init init
:loader (:loader @cp/cp-state)})))) :loader (:loader @cp/cp-state)}))))
expression (str/join " " expressions) ;; this might mess with the locations... expression (str/join " " expressions) ;; this might mess with the locations...
exit-code exit-code
;; handle preloads ;; handle preloads
(if exit-code exit-code (if exit-code exit-code
(do (when preloads (do (when preloads
(sci/binding [sci/file "<preloads>"] (sci/binding [sci/file "<preloads>"]
(try (try
(sci/eval-string* sci-ctx preloads) (sci/eval-string* sci-ctx preloads)
(catch Throwable e (catch Throwable e
(error-handler e {:expression expression (error-handler e {:expression expression
:debug debug :debug debug
:preloads preloads :preloads preloads
:init init :init init
:loader (:loader @cp/cp-state)}))))) :loader (:loader @cp/cp-state)})))))
nil)) nil))
exit-code exit-code
;; handle --init ;; handle --init
(if exit-code exit-code (if exit-code exit-code
(do (when init (do (when init
(try (try
(load-file* init) (load-file* init)
(catch Throwable e (catch Throwable e
(error-handler e {:expression expression (error-handler e {:expression expression
:debug debug :debug debug
:preloads preloads :preloads preloads
:init init :init init
:loader (:loader @cp/cp-state)})))) :loader (:loader @cp/cp-state)}))))
nil)) nil))
;; socket REPL is start asynchronously. when no other args are ;; socket REPL is start asynchronously. when no other args are
;; provided, a normal REPL will be started as well, which causes the ;; provided, a normal REPL will be started as well, which causes the
;; process to wait until SIGINT ;; process to wait until SIGINT
_ (when socket-repl (start-socket-repl! socket-repl sci-ctx)) _ (when socket-repl (start-socket-repl! socket-repl sci-ctx))
exit-code exit-code
(or exit-code (or exit-code
(second (second
(cond version-opt (cond version-opt
[(print-version) 0] [(print-version) 0]
help (print-help sci-ctx command-line-args) help (print-help sci-ctx command-line-args)
doc (print-doc sci-ctx command-line-args) doc (print-doc sci-ctx command-line-args)
describe? describe?
[(print-describe) 0] [(print-describe) 0]
repl [(repl/start-repl! sci-ctx) 0] repl [(repl/start-repl! sci-ctx) 0]
nrepl [(start-nrepl! nrepl sci-ctx) 0] nrepl [(start-nrepl! nrepl sci-ctx) 0]
uberjar [nil 0] uberjar [nil 0]
list-tasks [(tasks/list-tasks sci-ctx) 0] list-tasks [(tasks/list-tasks sci-ctx) 0]
print-deps [(print-deps/print-deps (:print-deps-format cli-opts)) 0] print-deps [(print-deps/print-deps (:print-deps-format cli-opts)) 0]
uberscript uberscript
[nil (do (uberscript/uberscript {:ctx sci-ctx [nil (do (uberscript/uberscript {:ctx sci-ctx
:expressions expressions}) :expressions expressions})
0)] 0)]
expressions expressions
;; execute code ;; execute code
(sci/binding [sci/file abs-path] (sci/binding [sci/file abs-path]
(try (try
; when evaluating expression(s), add in repl-requires so things like ; when evaluating expression(s), add in repl-requires so things like
; pprint and dir are available ; pprint and dir are available
(sci/eval-form sci-ctx `(apply require (quote ~clojure-main/repl-requires))) (sci/eval-form sci-ctx `(apply require (quote ~clojure-main/repl-requires)))
(loop [] (loop []
(let [in (read-next *in*)] (let [in (read-next *in*)]
(if (identical? ::EOF in) (if (identical? ::EOF in)
[nil 0] ;; done streaming [nil 0] ;; done streaming
(let [res [(let [res (let [res [(let [res
(sci/binding [sci/file (or @sci/file "<expr>") (sci/binding [sci/file (or @sci/file "<expr>")
input-var in input-var in
core/command-line-args command-line-args] core/command-line-args command-line-args]
(sci/eval-string* sci-ctx expression))] (sci/eval-string* sci-ctx expression))]
;; return value printing ;; return value printing
(when (and (some? res) (when (and (some? res)
(or (not run) (or (not run)
(:prn cli-opts))) (:prn cli-opts)))
(if-let [pr-f (cond shell-out println (if-let [pr-f (cond shell-out println
edn-out prn)] edn-out prn)]
(if (sequential? res) (if (sequential? res)
(doseq [l res (doseq [l res
:while (not (pipe-signal-received?))] :while (not (pipe-signal-received?))]
(pr-f l)) (pr-f l))
(pr-f res)) (pr-f res))
(prn res)))) 0]] (prn res)))) 0]]
(if stream? (if stream?
(recur) (recur)
res))))) res)))))
(catch Throwable e (catch Throwable e
(error-handler e {:expression expression (error-handler e {:expression expression
:debug debug :debug debug
:preloads preloads :preloads preloads
:loader (:loader @cp/cp-state)})))) :loader (:loader @cp/cp-state)}))))
clojure [nil (if-let [proc (bdeps/clojure command-line-args)] clojure [nil (if-let [proc (bdeps/clojure command-line-args)]
(-> @proc :exit) (-> @proc :exit)
0)] 0)]
:else [(repl/start-repl! sci-ctx) 0])) :else [(repl/start-repl! sci-ctx) 0]))
1)] 1)]
(flush) (flush)
(when uberscript (when uberscript
(let [uberscript-out uberscript] (let [uberscript-out uberscript]
(spit uberscript-out "") ;; reset file (spit uberscript-out "") ;; reset file
(doseq [s (distinct @uberscript-sources)] (doseq [s (distinct @uberscript-sources)]
(spit uberscript-out s :append true)) (spit uberscript-out s :append true))
(spit uberscript-out preloads :append true) (spit uberscript-out preloads :append true)
(spit uberscript-out expression :append true))) (spit uberscript-out expression :append true)))
(when uberjar (when uberjar
(if-let [cp (cp/get-classpath)] (if-let [cp (cp/get-classpath)]
(uberjar/run {:dest uberjar (uberjar/run {:dest uberjar
:jar :uber :jar :uber
:classpath cp :classpath cp
:main-class main :main-class main
:verbose debug}) :verbose debug})
(throw (Exception. "The uberjar task needs a classpath.")))) (throw (Exception. "The uberjar task needs a classpath."))))
exit-code)))) exit-code))))
(defn satisfies-min-version? [min-version] (defn satisfies-min-version? [min-version]
(let [[major-current minor-current patch-current] version-data (let [[major-current minor-current patch-current] version-data
[major-min minor-min patch-min] (parse-version min-version)] [major-min minor-min patch-min] (parse-version min-version)]
(or (> major-current major-min) (or (> major-current major-min)
(and (= major-current major-min) (and (= major-current major-min)
(or (> minor-current minor-min) (or (> minor-current minor-min)
(and (= minor-current minor-min) (and (= minor-current minor-min)
(>= patch-current patch-min))))))) (>= patch-current patch-min)))))))
(defn main [& args] (defn main [& args]
(let [bb-edn-file (or (System/getenv "BABASHKA_EDN") (let [[args global-opts] (parse-global-opts args)
"bb.edn") bb-edn-file (or (:config global-opts)
bb-edn (or (when (fs/exists? bb-edn-file) "bb.edn")
(let [raw-string (slurp bb-edn-file) bb-edn (when (fs/exists? bb-edn-file)
edn (edn/read-string raw-string) (let [raw-string (slurp bb-edn-file)
edn (assoc edn :raw raw-string)] edn (edn/read-string raw-string)
(vreset! common/bb-edn edn))) edn (assoc edn
;; tests may have modified bb-edn :raw raw-string
@common/bb-edn) :file bb-edn-file
min-bb-version (:min-bb-version bb-edn)] :deps-root
(when min-bb-version (or (:deps-root global-opts)
(when-not (satisfies-min-version? min-bb-version) (str (fs/parent bb-edn-file))))]
(binding [*out* *err*] (vreset! common/bb-edn edn)))
(println (str "WARNING: this project requires babashka " min-bb-version (:min-bb-version bb-edn)]
min-bb-version " or newer, but you have: " version)))))) (when min-bb-version
(let [opts (parse-opts args)] (when-not (satisfies-min-version? min-bb-version)
(exec opts))) (binding [*out* *err*]
(println (str "WARNING: this project requires babashka "
min-bb-version " or newer, but you have: " version)))))
(exec (parse-opts args global-opts))))
(def musl? (def musl?
"Captured at compile time, to know if we are running inside a "Captured at compile time, to know if we are running inside a
statically compiled executable with musl." statically compiled executable with musl."
(and (= "true" (System/getenv "BABASHKA_STATIC")) (and (= "true" (System/getenv "BABASHKA_STATIC"))
(= "true" (System/getenv "BABASHKA_MUSL")))) (= "true" (System/getenv "BABASHKA_MUSL"))))
(defmacro run [args] (defmacro run [args]
(if musl? (if musl?
;; When running in musl-compiled static executable we lift execution of bb ;; When running in musl-compiled static executable we lift execution of bb
;; inside a thread, so we have a larger than default stack size, set by an ;; inside a thread, so we have a larger than default stack size, set by an
;; argument to the linker. See https://github.com/oracle/graal/issues/3398 ;; argument to the linker. See https://github.com/oracle/graal/issues/3398
`(let [v# (volatile! nil) `(let [v# (volatile! nil)
f# (fn [] f# (fn []
(vreset! v# (apply main ~args)))] (vreset! v# (apply main ~args)))]
(doto (Thread. nil f# "main") (doto (Thread. nil f# "main")
(.start) (.start)
(.join)) (.join))
@v#) @v#)
`(apply main ~args))) `(apply main ~args)))
(defn -main (defn -main
[& args] [& args]
(handle-pipe!) (handle-pipe!)
(handle-sigint!) (handle-sigint!)
(if-let [dev-opts (System/getenv "BABASHKA_DEV")] (if-let [dev-opts (System/getenv "BABASHKA_DEV")]
(let [{:keys [:n]} (if (= "true" dev-opts) {:n 1} (let [{:keys [:n]} (if (= "true" dev-opts) {:n 1}
(edn/read-string dev-opts)) (edn/read-string dev-opts))
last-iteration (dec n)] last-iteration (dec n)]
(dotimes [i n] (dotimes [i n]
(if (< i last-iteration) (if (< i last-iteration)
(with-out-str (apply main args)) (with-out-str (apply main args))
(do (run args) (do (run args)
(binding [*out* *err*] (binding [*out* *err*]
(println "ran" n "times")))))) (println "ran" n "times"))))))
(let [exit-code (run args)] (let [exit-code (run args)]
(System/exit exit-code)))) (System/exit exit-code))))
;;;; Scratch ;;;; Scratch

View file

@ -414,7 +414,7 @@
(is (= x (json/read-str (with-out-str (json/pprint x))))))) (is (= x (json/read-str (with-out-str (json/pprint x)))))))
(deftest pretty-print-nonescaped-unicode (deftest pretty-print-nonescaped-unicode
(is (= "\"\u1234\u4567\"\n" (is (= (str "\"\u1234\u4567\"" (System/lineSeparator))
(with-out-str (with-out-str
(json/pprint "\u1234\u4567" :escape-unicode false))))) (json/pprint "\u1234\u4567" :escape-unicode false)))))

View file

@ -15,7 +15,7 @@
+---+---+ +---+---+
| 3 | 4 | | 3 | 4 |
+---+---+ +---+---+
") "\n") ") (System/lineSeparator))
(with-out-str (table [["1" "2"] ["3" "4"]]))))) (with-out-str (table [["1" "2"] ["3" "4"]])))))
(deftest test-table-with-vecs-in-vec (deftest test-table-with-vecs-in-vec

View file

@ -1,12 +1,14 @@
(ns babashka.bb-edn-test (ns babashka.bb-edn-test
(:require (:require
[babashka.fs :as fs] [babashka.fs :as fs]
[babashka.impl.classpath :as cp]
[babashka.impl.common :as common] [babashka.impl.common :as common]
[babashka.main :as main] [babashka.main :as main]
[babashka.test-utils :as test-utils] [babashka.test-utils :as test-utils]
[clojure.edn :as edn] [clojure.edn :as edn]
[clojure.string :as str] [clojure.string :as str]
[clojure.test :as test :refer [deftest is testing]])) [clojure.test :as test :refer [deftest is testing]]
[sci.core :as sci]))
(defn bb [& args] (defn bb [& args]
(let [args (map str args) (let [args (map str args)
@ -220,7 +222,10 @@
t1 (System/currentTimeMillis) t1 (System/currentTimeMillis)
delta-parallel (- t1 t0)] delta-parallel (- t1 t0)]
(is (= tree s)) (is (= tree s))
(is (< delta-parallel delta-sequential)))))) (when (>= (doto (-> (Runtime/getRuntime) (.availableProcessors))
(prn))
2)
(is (< delta-parallel delta-sequential)))))))
(testing "exception" (testing "exception"
(test-utils/with-config '{:tasks {a (Thread/sleep 10000) (test-utils/with-config '{:tasks {a (Thread/sleep 10000)
b (do (Thread/sleep 10) b (do (Thread/sleep 10)
@ -337,20 +342,24 @@
(is (= "uberjar" (:file (main/parse-opts ["uberjar"])))) (is (= "uberjar" (:file (main/parse-opts ["uberjar"]))))
(finally (fs/delete "uberjar")))))) (finally (fs/delete "uberjar"))))))
(deftest min-bb-version (deftest min-bb-version-test
(when-not test-utils/native? (fs/with-temp-dir [dir {}]
(vreset! common/bb-edn '{:min-bb-version "300.0.0"}) (let [config (str (fs/file dir "bb.edn"))]
(let [sw (java.io.StringWriter.)] (spit config '{:min-bb-version "300.0.0"})
(binding [*err* sw] (let [sw (java.io.StringWriter.)]
(main/main "-e" "nil")) (binding [*err* sw]
(is (str/includes? (str sw) (main/main "--config" config "-e" "nil"))
"WARNING: this project requires babashka 300.0.0 or newer, but you have: "))))) (is (str/includes? (str sw)
"WARNING: this project requires babashka 300.0.0 or newer, but you have: "))))))
;; TODO: (deftest classpath-other-bb-edn-test
;; Do we want to support the same parsing as the clj CLI? (fs/with-temp-dir [dir {}]
;; Or do we want `--aliases :foo:bar` (let [config (str (fs/file dir "bb.edn"))]
;; Let's wait for a good use case (spit config '{:paths ["src"]
#_(deftest alias-deps-test :tasks {cp (prn (babashka.classpath/get-classpath))}})
(test-utils/with-config '{:aliases {:medley {:deps {medley/medley {:mvn/version "1.3.0"}}}}} (let [out (bb "--config" config "cp")
(is (= '{1 {:id 1}, 2 {:id 2}} entries (cp/split-classpath out)
(bb "-A:medley" "-e" "(require 'medley.core)" "-e" "(medley.core/index-by :id [{:id 1} {:id 2}])"))))) entry (first entries)]
(is (= 1 (count entries)))
(is (= (fs/parent config) (fs/parent entry)))
(is (str/ends-with? entry "src"))))))

View file

@ -18,30 +18,34 @@
:eof nil} :eof nil}
(apply test-utils/bb (when (some? input) (str input)) (map str args))))) (apply test-utils/bb (when (some? input) (str input)) (map str args)))))
(defn parse-opts [args]
(let [[args global-opts] (main/parse-global-opts args)]
(main/parse-opts args global-opts)))
(deftest parse-opts-test (deftest parse-opts-test
(is (= "1667" (is (= "1667"
(:nrepl (main/parse-opts ["--nrepl-server"])))) (:nrepl (parse-opts ["--nrepl-server"]))))
(is (= "1666" (is (= "1666"
(:socket-repl (main/parse-opts ["--socket-repl"])))) (:socket-repl (parse-opts ["--socket-repl"]))))
(is (= {:nrepl "1667", :classpath "src"} (is (= {:nrepl "1667", :classpath "src"}
(main/parse-opts ["--nrepl-server" "-cp" "src"]))) (parse-opts ["--nrepl-server" "-cp" "src"])))
(is (= {:nrepl "1667", :classpath "src"} (is (= {:nrepl "1667", :classpath "src"}
(main/parse-opts ["-cp" "src" "nrepl-server"]))) (parse-opts ["-cp" "src" "nrepl-server"])))
(is (= {:socket-repl "1666", :expressions ["123"]} (is (= {:socket-repl "1666", :expressions ["123"]}
(main/parse-opts ["--socket-repl" "-e" "123"]))) (parse-opts ["--socket-repl" "-e" "123"])))
(is (= {:socket-repl "1666", :expressions ["123"]} (is (= {:socket-repl "1666", :expressions ["123"]}
(main/parse-opts ["--socket-repl" "1666" "-e" "123"]))) (parse-opts ["--socket-repl" "1666" "-e" "123"])))
(is (= {:nrepl "1666", :expressions ["123"]} (is (= {:nrepl "1666", :expressions ["123"]}
(main/parse-opts ["--nrepl-server" "1666" "-e" "123"]))) (parse-opts ["--nrepl-server" "1666" "-e" "123"])))
(is (= {:classpath "src" (is (= {:classpath "src"
:uberjar "foo.jar"} :uberjar "foo.jar"}
(main/parse-opts ["--classpath" "src" "uberjar" "foo.jar"]))) (parse-opts ["--classpath" "src" "uberjar" "foo.jar"])))
(is (= {:classpath "src" (is (= {:classpath "src"
:uberjar "foo.jar" :uberjar "foo.jar"
:debug true} :debug true}
(main/parse-opts ["--debug" "--classpath" "src" "uberjar" "foo.jar"]))) (parse-opts ["--debug" "--classpath" "src" "uberjar" "foo.jar"])))
(is (= "src" (:classpath (main/parse-opts ["--classpath" "src"])))) (is (= "src" (:classpath (parse-opts ["--classpath" "src"]))))
(is (:debug (main/parse-opts ["--debug"]))) (is (:debug (parse-opts ["--debug"])))
(is (= 123 (bb nil "(println 123)"))) (is (= 123 (bb nil "(println 123)")))
(is (= 123 (bb nil "-e" "(println 123)"))) (is (= 123 (bb nil "-e" "(println 123)")))
(is (= 123 (bb nil "--eval" "(println 123)"))) (is (= 123 (bb nil "--eval" "(println 123)")))
@ -54,8 +58,8 @@
(let [v (bb nil "--describe")] (let [v (bb nil "--describe")]
(is (:babashka/version v)) (is (:babashka/version v))
(is (:feature/xml v))) (is (:feature/xml v)))
(is (= {:force? true} (main/parse-opts ["--force"]))) (is (= {:force? true} (parse-opts ["--force"])))
(is (= {:main "foo", :command-line-args '("-h")} (main/parse-opts ["-m" "foo" "-h"])))) (is (= {:main "foo", :command-line-args '("-h")} (parse-opts ["-m" "foo" "-h"]))))
(deftest version-test (deftest version-test
(is (= [1 0 0] (main/parse-version "1.0.0-SNAPSHOT"))) (is (= [1 0 0] (main/parse-version "1.0.0-SNAPSHOT")))

View file

@ -47,13 +47,10 @@
(defn bb-jvm [input-or-opts & args] (defn bb-jvm [input-or-opts & args]
(reset! cp/cp-state nil) (reset! cp/cp-state nil)
(reset! main/env {}) (reset! main/env {})
(if-let [path *bb-edn-path*] (vreset! common/bb-edn nil)
(let [raw (slurp path)] (let [args (cond-> args *bb-edn-path*
(vreset! common/bb-edn (->> (list* "--config" *bb-edn-path* "--deps-root" ".")))
(assoc (edn/read-string raw) os (java.io.StringWriter.)
:raw raw)))
(vreset! common/bb-edn nil))
(let [os (java.io.StringWriter.)
es (if-let [err (:err input-or-opts)] es (if-let [err (:err input-or-opts)]
err (java.io.StringWriter.)) err (java.io.StringWriter.))
in (if (string? input-or-opts) in (if (string? input-or-opts)
@ -76,7 +73,9 @@
(apply main/main args)))] (apply main/main args)))]
(if (zero? res) (if (zero? res)
(do (do
(println (str es)) ;; flush stderr (let [err (str es)]
(when-not (str/blank? err)
(println err))) ;; flush stderr
(normalize (str os))) (normalize (str os)))
(do (do
(println (str os)) (println (str os))
@ -89,14 +88,12 @@
(vars/bindRoot sci/err *err*))))) (vars/bindRoot sci/err *err*)))))
(defn bb-native [input & args] (defn bb-native [input & args]
(let [res (p/process (into ["./bb"] args) (let [args (cond-> args *bb-edn-path*
(cond-> {:in input (->> (list* "--config" *bb-edn-path* "--deps-root" ".")))
:out :string res (p/process (into ["./bb"] args)
:err :string} {:in input
*bb-edn-path* :out :string
(assoc :err :string})
:extra-env (assoc (into {} (System/getenv))
"BABASHKA_EDN" *bb-edn-path*))))
res (deref res) res (deref res)
exit (:exit res) exit (:exit res)
error? (pos? exit)] error? (pos? exit)]

View file

@ -45,16 +45,6 @@
(is (= "(\"42\")\n" (tu/bb nil "--jar" path "-m" "my.main-main" "42"))) (is (= "(\"42\")\n" (tu/bb nil "--jar" path "-m" "my.main-main" "42")))
(is (= "(\"42\")\n" (tu/bb nil "--classpath" path "-m" "my.main-main" "42"))) (is (= "(\"42\")\n" (tu/bb nil "--classpath" path "-m" "my.main-main" "42")))
(is (= "(\"42\")\n" (tu/bb nil path "42")))))) (is (= "(\"42\")\n" (tu/bb nil path "42"))))))
; this test fails the windows native test in CI
(when-not main/windows?
(testing "throw on empty classpath"
(let [tmp-file (java.io.File/createTempFile "uber" ".jar")
path (.getPath tmp-file)]
(.deleteOnExit tmp-file)
(is (thrown-with-msg?
Exception #"classpath"
(tu/bb nil "uberjar" path "-m" "my.main-main"))))))
(testing "ignore empty entries on classpath" (testing "ignore empty entries on classpath"
(let [tmp-file (java.io.File/createTempFile "uber" ".jar") (let [tmp-file (java.io.File/createTempFile "uber" ".jar")
path (.getPath tmp-file) path (.getPath tmp-file)
@ -63,3 +53,14 @@
(tu/bb nil "--classpath" empty-classpath "uberjar" path "-m" "my.main-main") (tu/bb nil "--classpath" empty-classpath "uberjar" path "-m" "my.main-main")
;; Only a manifest entry is added ;; Only a manifest entry is added
(is (< (count-entries path) 3))))) (is (< (count-entries path) 3)))))
(deftest throw-on-empty-classpath
;; this test fails the windows native test in CI
(when-not main/windows?
(testing "throw on empty classpath"
(let [tmp-file (java.io.File/createTempFile "uber" ".jar")
path (.getPath tmp-file)]
(.deleteOnExit tmp-file)
(is (thrown-with-msg?
Exception #"classpath"
(tu/bb nil "uberjar" path "-m" "my.main-main")))))))