This commit is contained in:
Michiel Borkent 2021-03-16 17:38:50 +01:00
parent d99f813fe8
commit 4d77ee6446

View file

@ -471,7 +471,7 @@ Use -- to separate script command line args from bb command line args.
(assoc opts-map :main (first options)))) (assoc opts-map :main (first options))))
(":do") (":do")
(let [options (next options) (let [options (next options)
options (into [] (comp (partition-by #(= % ",")) options (into [] (comp (partition-by #(= % ":do"))
(take-nth 2)) (take-nth 2))
options) options)
parsed (map parse-opts options)] parsed (map parse-opts options)]
@ -509,8 +509,9 @@ Use -- to separate script command line args from bb command line args.
;; this is for invoking babashka itself with command-line-args ;; this is for invoking babashka itself with command-line-args
(cond cmd-line-args (cond cmd-line-args
(parse-opts (seq (map str (concat cmd-line-args command-line-args)))) (parse-opts (seq (map str (concat cmd-line-args command-line-args))))
proc (do (-> proc (p/process {:inherit true}) p/check) proc {:exec (fn []
{:exit-code 0}))) (-> proc (p/process {:inherit true}) p/check)
0)}))
(error (str "No such task: " task) 1))) (error (str "No such task: " task) 1)))
(error (str "File does not exist: " task) 1)))) (error (str "File does not exist: " task) 1))))
@ -519,186 +520,186 @@ Use -- to separate script command line args from bb command line args.
(sci/binding [reflection-var false (sci/binding [reflection-var false
core/data-readers @core/data-readers core/data-readers @core/data-readers
sci/ns @sci/ns] sci/ns @sci/ns]
(let [{version-opt :version (if-let [f (:exec opts)]
:keys [:shell-in :edn-in :shell-out :edn-out (f)
:help? :file :command-line-args (let [{version-opt :version
:expressions :stream? :keys [:shell-in :edn-in :shell-out :edn-out
:repl :socket-repl :nrepl :help? :file :command-line-args
:verbose? :classpath :expressions :stream?
:main :uberscript :describe? :repl :socket-repl :nrepl
:jar :uberjar :clojure :verbose? :classpath
:exit-code] :as opts} :main :uberscript :describe?
opts :jar :uberjar :clojure] :as opts}
_ (when clojure opts
(if-let [proc (deps/clojure (:opts opts))] _ (when clojure
(-> @proc :exit (System/exit)) (if-let [proc (deps/clojure (:opts opts))]
(System/exit 0))) (-> @proc :exit (System/exit))
_ (when verbose? (vreset! common/verbose? true)) (System/exit 0)))
_ (do ;; set properties _ (when verbose? (vreset! common/verbose? true))
(when main (System/setProperty "babashka.main" main)) _ (do ;; set properties
(System/setProperty "babashka.version" version)) (when main (System/setProperty "babashka.main" main))
read-next (fn [*in*] (System/setProperty "babashka.version" version))
(if (pipe-signal-received?) read-next (fn [*in*]
::EOF (if (pipe-signal-received?)
(if stream? ::EOF
(if shell-in (or (read-line) ::EOF) (if stream?
(edn/read {:readers edn-readers (if shell-in (or (read-line) ::EOF)
:eof ::EOF} *in*)) (edn/read {:readers edn-readers
(delay (cond shell-in :eof ::EOF} *in*))
(shell-seq *in*) (delay (cond shell-in
edn-in (shell-seq *in*)
(edn-seq *in*) edn-in
:else (edn-seq *in*)
(edn/read {:readers edn-readers} *in*)))))) :else
uberscript-sources (atom ()) (edn/read {:readers edn-readers} *in*))))))
env (atom {}) uberscript-sources (atom ())
classpath (or classpath env (atom {})
(System/getenv "BABASHKA_CLASSPATH")) classpath (or classpath
_ (when classpath (System/getenv "BABASHKA_CLASSPATH"))
(cp/add-classpath classpath)) _ (when classpath
abs-path (when file (cp/add-classpath classpath))
(let [abs-path (.getAbsolutePath (io/file file))] abs-path (when file
(vars/bindRoot sci/file abs-path) (let [abs-path (.getAbsolutePath (io/file file))]
(System/setProperty "babashka.file" abs-path) (vars/bindRoot sci/file abs-path)
abs-path)) (System/setProperty "babashka.file" abs-path)
_ (when jar abs-path))
(cp/add-classpath jar)) _ (when jar
load-fn (fn [{:keys [:namespace :reload]}] (cp/add-classpath jar))
(when-let [{:keys [:loader]} load-fn (fn [{:keys [:namespace :reload]}]
@cp/cp-state] (when-let [{:keys [:loader]}
(if ;; ignore built-in namespaces when uberscripting, unless with :reload @cp/cp-state]
(and uberscript (if ;; ignore built-in namespaces when uberscripting, unless with :reload
(not reload) (and uberscript
(or (contains? namespaces namespace) (not reload)
(contains? sci-namespaces/namespaces namespace))) (or (contains? namespaces namespace)
"" (contains? sci-namespaces/namespaces namespace)))
(let [res (cp/source-for-namespace loader namespace nil)] ""
(when uberscript (swap! uberscript-sources conj (:source res))) (let [res (cp/source-for-namespace loader namespace nil)]
res)))) (when uberscript (swap! uberscript-sources conj (:source res)))
main (if (and jar (not main)) res))))
(when-let [res (cp/getResource main (if (and jar (not main))
(cp/loader jar) (when-let [res (cp/getResource
["META-INF/MANIFEST.MF"] {:url? true})] (cp/loader jar)
(cp/main-ns res)) ["META-INF/MANIFEST.MF"] {:url? true})]
main) (cp/main-ns res))
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
'*command-line-args* '*command-line-args*
(sci/new-dynamic-var '*command-line-args* command-line-args) (sci/new-dynamic-var '*command-line-args* command-line-args)
'*warn-on-reflection* reflection-var '*warn-on-reflection* reflection-var
'load-file load-file*)) 'load-file load-file*))
(assoc-in ['clojure.java.io 'resource] (assoc-in ['clojure.java.io 'resource]
(fn [path] (fn [path]
(when-let [{:keys [:loader]} @cp/cp-state] (when-let [{:keys [:loader]} @cp/cp-state]
(if (str/starts-with? path "/") nil ;; non-relative paths always return nil (if (str/starts-with? path "/") nil ;; non-relative paths always return nil
(cp/getResource loader [path] {:url? true}))))) (cp/getResource loader [path] {:url? true})))))
(assoc-in ['user (with-meta '*input* (assoc-in ['user (with-meta '*input*
(when-not stream? (when-not stream?
{:sci.impl/deref! true}))] input-var)) {:sci.impl/deref! true}))] input-var))
:env env :env env
:features #{:bb :clj} :features #{:bb :clj}
:classes classes/class-map :classes classes/class-map
:imports imports :imports 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]
(if exit-code [nil exit-code] (cond expressions [expressions nil]
(cond expressions [expressions nil] main [[(format "(ns user (:require [%1$s])) (apply %1$s/-main *command-line-args*)"
main [[(format "(ns user (:require [%1$s])) (apply %1$s/-main *command-line-args*)" main)] nil]
main)] nil] 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 :verbose? verbose?
:verbose? verbose? :preloads preloads
:preloads preloads :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 :verbose? verbose?
:verbose? verbose? :preloads preloads
:preloads preloads :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?
help? [(print-help) 0]
[(print-help) 0] 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] expressions
expressions (sci/binding [sci/file abs-path]
(sci/binding [sci/file abs-path] (try
(try (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] (sci/eval-string* sci-ctx expression))]
(sci/eval-string* sci-ctx expression))] (when (some? res)
(when (some? res) (if-let [pr-f (cond shell-out println
(if-let [pr-f (cond shell-out println edn-out prn)]
edn-out prn)] (if (coll? res)
(if (coll? 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 :verbose? verbose?
:verbose? verbose? :preloads preloads
:preloads preloads :loader (:loader @cp/cp-state)}))))
:loader (:loader @cp/cp-state)})))) uberscript [nil 0]
uberscript [nil 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 (uberjar/run {:dest uberjar
(uberjar/run {:dest uberjar :jar :uber
:jar :uber :classpath classpath
:classpath classpath :main-class main
:main-class main :verbose verbose?}))
:verbose verbose?})) exit-code)))))
exit-code))))
(defn main [& args] (defn main [& args]
(let [opts (parse-opts args)] (let [opts (parse-opts args)]