diff --git a/.circleci/config.yml b/.circleci/config.yml index 0b9b49dd..0b30d8fb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -30,6 +30,10 @@ jobs: wget -nc https://download.clojure.org/install/linux-install-1.10.1.447.sh chmod +x linux-install-1.10.1.447.sh sudo ./linux-install-1.10.1.447.sh + - run: + name: Install lsof + command: | + sudo apt-get install lsof - run: name: Download GraalVM command: | @@ -83,6 +87,10 @@ jobs: wget https://download.clojure.org/install/linux-install-1.10.1.447.sh chmod +x linux-install-1.10.1.447.sh sudo ./linux-install-1.10.1.447.sh + - run: + name: Install lsof + command: | + sudo apt-get install lsof - run: name: Install native dev tools command: | diff --git a/sci b/sci index ade0d29a..4ab01bd9 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit ade0d29a4d3d97d9d6c958434368d5fa4359debf +Subproject commit 4ab01bd92cc87511f478c861c84b40c6e208eeae diff --git a/src/babashka/main.clj b/src/babashka/main.clj index ab30b098..8317fb0c 100644 --- a/src/babashka/main.clj +++ b/src/babashka/main.clj @@ -61,7 +61,8 @@ (recur (rest options) (assoc opts-map :socket-repl (first options)))) - (if (not (:file opts-map)) + (if (not (or (:file opts-map) + (:socket-repl opts-map))) (assoc opts-map :expression opt :command-line-args (rest options)) @@ -177,6 +178,15 @@ (let [s (slurp file)] (sci/eval-string s ctx))) +(defn start-socket-repl! [address ctx read-next] + (let [ctx (update ctx :bindings assoc + (with-meta '*in* + {:sci/deref! true}) + (read-next))] + (socket-repl/start-repl! address ctx) + ;; hang until SIGINT + @(promise))) + (defn main [& args] (handle-pipe!) @@ -187,17 +197,18 @@ :help? :file :command-line-args :expression :stream? :time? :socket-repl] :as _opts} (parse-opts args) - read-next #(if (pipe-signal-received?) - ::EOF - (if stream? - (if shell-in (or (read-line) ::EOF) - (read-edn)) - (delay (cond shell-in - (shell-seq *in*) - edn-in - (edn-seq *in*) - :else - (edn/read *in*))))) + read-next (fn [*in*] + (if (pipe-signal-received?) + ::EOF + (if stream? + (if shell-in (or (read-line) ::EOF) + (read-edn)) + (delay (cond shell-in + (shell-seq *in*) + edn-in + (edn-seq *in*) + :else + (edn/read *in*)))))) env (atom {}) ctx {:bindings (assoc bindings '*command-line-args* command-line-args) :env env} @@ -212,12 +223,11 @@ [(print-version) 0] help? [(print-help) 0] - socket-repl [(do (socket-repl/start-repl! socket-repl ctx) - @(promise)) 0] + socket-repl [(start-socket-repl! socket-repl ctx #(read-next *in*)) 0] :else (try (let [expr (if file (read-file file) expression)] - (loop [in (read-next)] + (loop [in (read-next *in*)] (let [ctx (update ctx :bindings assoc (with-meta '*in* (when-not stream? {:sci/deref! true})) in)] @@ -235,7 +245,7 @@ (pr-f res)) (prn res)))) 0]] (if stream? - (recur (read-next)) + (recur (read-next *in*)) res)))))) (catch Exception e (binding [*out* *err*] diff --git a/test/babashka/impl/socket_repl_test.clj b/test/babashka/impl/socket_repl_test.clj index 504767f2..e52a0940 100644 --- a/test/babashka/impl/socket_repl_test.clj +++ b/test/babashka/impl/socket_repl_test.clj @@ -11,21 +11,48 @@ (str/lower-case (System/getProperty "os.name")) "mac")) +(defn socket-command [expr] + (let [ret (sh "bash" "-c" + (format "echo \"%s\n:repl/exit\" | nc 127.0.0.1 1666" + (pr-str expr)))] + (:out ret))) + (deftest socket-repl-test - (when tu/jvm? - (try - (start-repl! "0.0.0.0:1666" {:env (atom {})}) - (is (str/includes? (:out (sh "bash" "-c" - "echo \"(+ 1 2 3)\n:repl/exit\" | nc 127.0.0.1 1666")) - "bb=> 6")) - (testing "ctrl-d exits normally, doesn't print nil" - (is (str/ends-with? (:out (sh "bash" "-c" - (if mac? ;; mac doesn't support -q - "echo \"(inc 1336)\" | nc 127.0.0.1 1666" - "echo \"(inc 1336)\" | nc -q 1 127.0.0.1 1666"))) - "1337\nbb=> "))) - (finally - (stop-repl!))))) + (try + (if tu/jvm? + (start-repl! "0.0.0.0:1666" {:bindings {(with-meta '*in* + {:sci/deref! true}) + (delay [1 2 3]) + '*command-line-args* + ["a" "b" "c"]} + :env (atom {})}) + (future + (sh "bash" "-c" + "echo '[1 2 3]' | ./bb --socket-repl 0.0.0.0:1666 a b c"))) + ;; wait for server to be available + (when tu/native? + (while (not (zero? (:exit + (sh "bash" "-c" + "lsof -t -i:1666")))))) + (is (str/includes? (socket-command '(+ 1 2 3)) + "bb=> 6")) + (testing "ctrl-d exits normally, doesn't print nil" + (is (str/ends-with? (:out (sh "bash" "-c" + (if mac? ;; mac doesn't support -q + "echo \"(inc 1336)\" | nc 127.0.0.1 1666" + "echo \"(inc 1336)\" | nc -q 1 127.0.0.1 1666"))) + "1337\nbb=> "))) + (testing "*in*" + (is (str/includes? (socket-command '*in*) + "[1 2 3]"))) + (testing "*command-line-args*" + (is (str/includes? (socket-command '*command-line-args*) + "\"a\" \"b\" \"c\""))) + (finally + (if tu/jvm? + (stop-repl!) + (sh "bash" "-c" + "kill -9 $(lsof -t -i:1666)"))))) ;;;; Scratch