|
| 1 | +; Copyright (c) Rich Hickey. All rights reserved. |
| 2 | +; The use and distribution terms for this software are covered by the |
| 3 | +; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) |
| 4 | +; which can be found in the file epl-v10.html at the root of this distribution. |
| 5 | +; By using this software in any fashion, you are agreeing to be bound by |
| 6 | +; the terms of this license. |
| 7 | +; You must not remove this notice, or any other, from this software. |
| 8 | +(ns clojure.tools.deps.interop |
| 9 | + "Functions for invoking Java processes and invoking tools via the Clojure CLI." |
| 10 | + (:require |
| 11 | + [clojure.java.process :as proc] |
| 12 | + [clojure.edn :as edn])) |
| 13 | + |
| 14 | +(defn ^:dynamic invoke-tool |
| 15 | + "Invoke tool using Clojure CLI. Args (one of :tool-alias or :tool-name, and :fn |
| 16 | + are required): |
| 17 | + :tool-alias - Tool alias to invoke (keyword) |
| 18 | + :tool-name - Name of installed tool to invoke (string or symbol) |
| 19 | + :fn - Function (symbol) |
| 20 | + :args - map of args to pass to function |
| 21 | +
|
| 22 | + Options: |
| 23 | + :command - CLI command, default=\"clojure\" |
| 24 | + :preserve-envelope - if true, return the full invocation envelope, default=false" |
| 25 | + {:added "1.12"} |
| 26 | + [{:keys [tool-name tool-alias fn args command preserve-envelope] |
| 27 | + :or {command "clojure", preserve-envelope false} |
| 28 | + :as opts}] |
| 29 | + (when-not (or tool-name tool-alias) (throw (ex-info "Either :tool-alias or :tool-name must be provided" (or opts {})))) |
| 30 | + (when-not (symbol? fn) (throw (ex-info (str "fn should be a symbol " fn) (or opts {})))) |
| 31 | + (let [args (assoc args :clojure.exec/invoke :fn) |
| 32 | + _ (when (:debug opts) (println "args" args)) |
| 33 | + command-strs [command (str "-T" (or tool-alias tool-name)) (pr-str fn) (pr-str args)] |
| 34 | + _ (when (:debug opts) (apply println "Invoking: " command-strs)) |
| 35 | + envelope (edn/read-string (apply proc/exec command-strs))] |
| 36 | + (if preserve-envelope |
| 37 | + envelope |
| 38 | + (let [{:keys [tag val]} envelope |
| 39 | + parsed-val (edn/read-string val)] |
| 40 | + (if (= :ret tag) |
| 41 | + parsed-val |
| 42 | + (throw (ex-info (:cause parsed-val) (or parsed-val {})))))))) |
| 43 | + |
| 44 | +(comment |
| 45 | + ;; regular invocation, should return {:hi :there} |
| 46 | + (invoke-tool {:tool-alias :deps, :fn 'clojure.core/identity, :args {:hi :there}}) |
| 47 | + |
| 48 | + ;; invocation throws, should return throwable map data |
| 49 | + (try |
| 50 | + (invoke-tool {:tool-alias :deps, :fn 'clojure.core/+, :args {:fail :here}}) |
| 51 | + (catch clojure.lang.ExceptionInfo e (ex-data e))) |
| 52 | + |
| 53 | + ;; capture stdout in returned envelope |
| 54 | + (let [resp (invoke-tool {:tool-alias :deps, |
| 55 | + :fn 'list |
| 56 | + :args {:format :edn |
| 57 | + :clojure.exec/out :capture} |
| 58 | + :preserve-envelope true})] |
| 59 | + (edn/read-string (:out resp))) |
| 60 | + |
| 61 | + ) |
0 commit comments