diff --git a/API.md b/API.md
new file mode 100644
index 0000000..5c66ae8
--- /dev/null
+++ b/API.md
@@ -0,0 +1,283 @@
+# Table of contents
+- [`borkdude.deps`](#borkdude.deps) - Port of https://github.com/clojure/brew-install/blob/1.11.1/src/main/resources/clojure/install/clojure in Clojure.
+ - [`*aux-process-fn*`](#borkdude.deps/*aux-process-fn*) - Invokes java
with arguments to calculate classpath, etc.
+ - [`*clojure-process-fn*`](#borkdude.deps/*clojure-process-fn*) - Invokes java
with arguments to clojure.main
to start Clojure.
+ - [`*clojure-tools-download-fn*`](#borkdude.deps/*clojure-tools-download-fn*) - Can be dynamically rebound to customise the download of the Clojure tools.
+ - [`*dir*`](#borkdude.deps/*dir*) - Directory in which deps.clj should be executed.
+ - [`*exit-fn*`](#borkdude.deps/*exit-fn*) - Function that is called on exit with :exit
code and :message
, an exceptional message when exit is non-zero.
+ - [`-main`](#borkdude.deps/-main) - See help-text
.
+ - [`clojure-tools-download!`](#borkdude.deps/clojure-tools-download!) - Downloads clojure tools archive in :out-dir
, if not already there, and extracts in-place the clojure tools jar file and other important files.
+ - [`clojure-tools-download-direct!`](#borkdude.deps/clojure-tools-download-direct!) - Downloads from :url
to :dest
file returning true on success.
+ - [`clojure-tools-download-java!`](#borkdude.deps/clojure-tools-download-java!) - Downloads :url
zip file to :dest
by invoking java
with :proxy
options on a .java
program file, and returns true on success.
+ - [`deps-clj-version`](#borkdude.deps/deps-clj-version) - The current version of deps.clj.
+ - [`get-cache-dir`](#borkdude.deps/get-cache-dir) - Returns cache dir (.cpcache
) from either local dir, if deps-edn
exists, or the user cache dir.
+ - [`get-config-dir`](#borkdude.deps/get-config-dir) - Retrieves configuration directory.
+ - [`get-config-paths`](#borkdude.deps/get-config-paths) - Returns vec of configuration paths, i.e.
+ - [`get-help`](#borkdude.deps/get-help) - Returns help text as string.
+ - [`get-install-dir`](#borkdude.deps/get-install-dir) - Retrieves the install directory where tools jar is located (after download).
+ - [`get-local-deps-edn`](#borkdude.deps/get-local-deps-edn) - Returns the path of the deps.edn
file (as string) in the current directory or as set by -Sdeps-file
.
+ - [`get-proxy-info`](#borkdude.deps/get-proxy-info) - Returns a map with proxy information parsed from env vars.
+ - [`parse-cli-opts`](#borkdude.deps/parse-cli-opts) - Parses the command line options.
+ - [`print-help`](#borkdude.deps/print-help) - Print help text.
+ - [`proxy-jvm-opts`](#borkdude.deps/proxy-jvm-opts) - Returns a vector containing the JVM system property arguments to be passed to a new process to set its proxy system properties.
+ - [`set-proxy-system-props!`](#borkdude.deps/set-proxy-system-props!) - Sets the proxy system properties in the current JVM.
+
+-----
+# borkdude.deps
+
+
+Port of https://github.com/clojure/brew-install/blob/1.11.1/src/main/resources/clojure/install/clojure in Clojure
+
+
+
+
+## `*aux-process-fn*`
+``` clojure
+
+(*aux-process-fn* {:keys [cmd out]})
+```
+
+Invokes `java` with arguments to calculate classpath, etc. May be
+ replacement by rebinding this dynamic var.
+
+ Called with a map of:
+
+ - `:cmd`: a vector of strings
+ - `:out`: if set to `:string`, `:out` key in result must contains stdout
+
+ Returns a map of:
+
+ - `:exit`, the exit code of the process
+ - `:out`, the string of stdout, if the input `:out` was set to `:string`
+
Source
+
+## `*clojure-process-fn*`
+``` clojure
+
+(*clojure-process-fn* {:keys [cmd]})
+```
+
+Invokes `java` with arguments to `clojure.main` to start Clojure. May
+ be replacement by rebinding this dynamic var.
+
+ Called with a map of:
+
+ - `:cmd`: a vector of strings
+
+ Must return a map of `:exit`, the exit code of te process.
+Source
+
+## `*clojure-tools-download-fn*`
+
+
+
+
+Can be dynamically rebound to customise the download of the Clojure tools.
+ Should be bound to a function accepting a map with:
+ - `:url`: The URL to download, as a string
+ - `:dest`: The path to the file to download it to, as a string
+ - `:proxy-opts`: a map as returned by [`get-proxy-info`](#borkdude.deps/get-proxy-info)
+ - `:clj-jvm-opts`: a vector of JVM opts (as passed on the command line).
+ Should return true if the `download` was successful, or false if not.
+Source
+
+## `*dir*`
+
+
+
+
+Directory in which deps.clj should be executed.
+Source
+
+## `*exit-fn*`
+``` clojure
+
+(*exit-fn* {:keys [exit message]})
+```
+
+Function that is called on exit with `:exit` code and `:message`, an exceptional message when exit is non-zero
+Source
+
+## `-main`
+``` clojure
+
+(-main & command-line-args)
+```
+
+See [`help-text`](#borkdude.deps/help-text).
+
+ In addition
+
+ - the values of the `CLJ_JVM_OPTS` and `JAVA_OPTIONS` environment
+ variables are passed to the java subprocess as command line options
+ when downloading dependencies and running any other commands
+ respectively.
+
+ - if the clojure tools jar cannot be located and the clojure tools
+ archive is not found, an attempt is made to download the archive
+ from the official site and extract its contents locally. The archive
+ is downloaded from this process directly, unless the `CLJ_JVM_OPTS`
+ env variable is set and a succesful attempt is made to download the
+ archive by invoking a java subprocess passing the env variable value
+ as command line options.
+Source
+
+## `clojure-tools-download!`
+``` clojure
+
+(clojure-tools-download! {:keys [out-dir debug proxy-opts clj-jvm-opts]})
+```
+
+Downloads clojure tools archive in `:out-dir`, if not already there,
+ and extracts in-place the clojure tools jar file and other important
+ files.
+
+ The download is attempted directly from this process, unless
+ `:jvm-opts` is set, in which case a java subprocess
+ is created to download the archive passing in its value as command
+ line options.
+
+ It calls [`*exit-fn*`](#borkdude.deps/*exit-fn*) if it cannot download the archive, with
+ instructions how to manually download it.
+Source
+
+## `clojure-tools-download-direct!`
+``` clojure
+
+(clojure-tools-download-direct! {:keys [url dest]})
+```
+
+Downloads from `:url` to `:dest` file returning true on success.
+Source
+
+## `clojure-tools-download-java!`
+``` clojure
+
+(clojure-tools-download-java! {:keys [url dest proxy-opts clj-jvm-opts]})
+```
+
+Downloads `:url` zip file to `:dest` by invoking `java` with
+ `:proxy` options on a `.java` program file, and returns true on
+ success. Requires Java 11+ (JEP 330).
+Source
+
+## `deps-clj-version`
+
+
+
+
+The current version of deps.clj
+Source
+
+## `get-cache-dir`
+``` clojure
+
+(get-cache-dir {:keys [deps-edn config-dir]})
+```
+
+Returns cache dir (`.cpcache`) from either local dir, if `deps-edn`
+ exists, or the user cache dir.
+Source
+
+## `get-config-dir`
+``` clojure
+
+(get-config-dir)
+```
+
+Retrieves configuration directory.
+ First tries `CLJ_CONFIG` env var, then `$XDG_CONFIG_HOME/clojure`, then ~/.clojure.
+Source
+
+## `get-config-paths`
+``` clojure
+
+(get-config-paths {:keys [cli-opts deps-edn config-dir install-dir]})
+```
+
+Returns vec of configuration paths, i.e. deps.edn from:
+ - `:install-dir` as obtained thrhough [`get-install-dir`](#borkdude.deps/get-install-dir)
+ - `:config-dir` as obtained through [`get-config-dir`](#borkdude.deps/get-config-dir)
+ - `:deps-edn` as obtained through [`get-local-deps-edn`](#borkdude.deps/get-local-deps-edn)
+Source
+
+## `get-help`
+``` clojure
+
+(get-help)
+```
+
+Returns help text as string.
+Source
+
+## `get-install-dir`
+``` clojure
+
+(get-install-dir)
+```
+
+Retrieves the install directory where tools jar is located (after download).
+ Defaults to ~/.deps.clj//ClojureTools.
+Source
+
+## `get-local-deps-edn`
+``` clojure
+
+(get-local-deps-edn {:keys [cli-opts]})
+```
+
+Returns the path of the `deps.edn` file (as string) in the current directory or as set by `-Sdeps-file`.
+ Required options:
+ * `:cli-opts`: command line options as parsed by `parse-opts`
+Source
+
+## `get-proxy-info`
+``` clojure
+
+(get-proxy-info)
+```
+
+Returns a map with proxy information parsed from env vars. The map
+ will contain :http-proxy and :https-proxy entries if the relevant
+ env vars are set and parsed correctly. The value for each is a map
+ with :host and :port entries.
+Source
+
+## `parse-cli-opts`
+``` clojure
+
+(parse-cli-opts args)
+```
+
+Parses the command line options.
+Source
+
+## `print-help`
+``` clojure
+
+(print-help)
+```
+
+Print help text
+Source
+
+## `proxy-jvm-opts`
+``` clojure
+
+(proxy-jvm-opts {:keys [http-proxy https-proxy]})
+```
+
+Returns a vector containing the JVM system property arguments to be passed to a new process
+ to set its proxy system properties.
+ proxy-info parameter is as returned from env-proxy-info.
+Source
+
+## `set-proxy-system-props!`
+``` clojure
+
+(set-proxy-system-props! {:keys [http-proxy https-proxy]})
+```
+
+Sets the proxy system properties in the current JVM.
+ proxy-info parameter is as returned from env-proxy-info.
+Source
diff --git a/bb.edn b/bb.edn
index 5e627e0..7f564dd 100644
--- a/bb.edn
+++ b/bb.edn
@@ -39,4 +39,11 @@
(run task)
(println))}
- upload-artifact {:task (exec 'artifact/upload)}}}
+ upload-artifact {:task (exec 'artifact/upload)}
+
+ quickdoc {:doc "Invoke quickdoc"
+ :extra-deps {io.github.borkdude/quickdoc {:git/sha "32e726cd6d785d00e49d4e614a05f7436d3831c0"}}
+ :task (exec 'quickdoc.api/quickdoc)
+ :exec-args {:git/branch "master"
+ :github/repo "https://github.com/borkdude/deps.clj"
+ :source-paths ["src"]}}}}
diff --git a/src/borkdude/deps.clj b/src/borkdude/deps.clj
index 9cdbb95..5c49338 100755
--- a/src/borkdude/deps.clj
+++ b/src/borkdude/deps.clj
@@ -11,21 +11,22 @@
(:gen-class))
(set! *warn-on-reflection* true)
-(def path-separator (System/getProperty "path.separator"))
+(def ^:private path-separator (System/getProperty "path.separator"))
;; see https://github.com/clojure/brew-install/blob/1.11.1/CHANGELOG.md
-(def version
+(def ^:private version
(delay (or (System/getenv "DEPS_CLJ_TOOLS_VERSION")
"1.11.1.1273")))
-(def cache-version "4")
+(def ^:private cache-version "4")
(def deps-clj-version
+ "The current version of deps.clj"
(-> (io/resource "DEPS_CLJ_VERSION")
(slurp)
(str/trim)))
-(defn warn [& strs]
+(defn- warn [& strs]
(binding [*out* *err*]
(apply println strs)))
@@ -35,22 +36,19 @@
(with-out-str
(apply println strs))))
-(def ^:private ^:dynamic *exit-fn*
- (fn
- ([exit-code] (System/exit exit-code))
- ([exit-code msg]
- (warn msg)
- (System/exit exit-code))))
+(defn ^:dynamic *exit-fn*
+ "Function that is called on exit with `:exit` code and `:message`, an exceptional message when exit is non-zero"
+ [{:keys [exit message]}]
+ (when message (warn message))
+ (System/exit exit))
-(def windows?
+(def ^:private windows?
(-> (System/getProperty "os.name")
(str/lower-case)
(str/includes? "windows")))
-(def ^:private ^:dynamic *dir* nil)
-
-(def ^:private ^:dynamic *env* nil)
-(def ^:private ^:dynamic *extra-env* nil)
+(def ^:dynamic *dir* "Directory in which deps.clj should be executed."
+ nil)
(defn- as-string-map
"Helper to coerce a Clojure map with keyword keys into something coerceable to Map
@@ -77,16 +75,17 @@
(.putAll (as-string-map env)))
pb)
-(defn shell-command
+(defn- internal-shell-command
"Executes shell command.
Accepts the following options:
`:to-string?`: instead of writing to stdoud, write to a string and
return it."
- ([args] (shell-command args nil))
- ([args {:keys [:to-string?]}]
- (let [args (mapv str args)
+ ([args] (internal-shell-command args nil))
+ ([args {:keys [out env extra-env]}]
+ (let [to-string? (= :string out)
+ args (mapv str args)
args (if (and windows? (not (System/getenv "DEPS_CLJ_NO_WINDOWS_FIXES")))
(mapv #(str/replace % "\"" "\\\"") args)
args)
@@ -96,9 +95,9 @@
true (.redirectInput ProcessBuilder$Redirect/INHERIT))
_ (when-let [dir *dir*]
(.directory pb (io/file dir)))
- _ (when-let [env *env*]
+ _ (when-let [env env]
(set-env pb env))
- _ (when-let [extra-env *extra-env*]
+ _ (when-let [extra-env extra-env]
(add-env pb extra-env))
proc (.start pb)
string-out
@@ -109,12 +108,39 @@
(str sw)))
exit-code (.waitFor proc)]
(when (not (zero? exit-code))
- (*exit-fn* exit-code))
- string-out)))
+ (*exit-fn* {:exit exit-code}))
+ {:out string-out
+ :exit exit-code})))
+
+(defn ^:dynamic *aux-process-fn*
+ "Invokes `java` with arguments to calculate classpath, etc. May be
+ replacement by rebinding this dynamic var.
+
+ Called with a map of:
+
+ - `:cmd`: a vector of strings
+ - `:out`: if set to `:string`, `:out` key in result must contains stdout
+
+ Returns a map of:
-(def ^:private ^:dynamic *process-fn* shell-command)
+ - `:exit`, the exit code of the process
+ - `:out`, the string of stdout, if the input `:out` was set to `:string`"
+ [{:keys [cmd out]}]
+ (internal-shell-command cmd {:out out}))
-(def help-text (delay (str "Version: " @version "
+(defn ^:dynamic *clojure-process-fn*
+ "Invokes `java` with arguments to `clojure.main` to start Clojure. May
+ be replacement by rebinding this dynamic var.
+
+ Called with a map of:
+
+ - `:cmd`: a vector of strings
+
+ Must return a map of `:exit`, the exit code of te process."
+ [{:keys [cmd]}]
+ (internal-shell-command cmd))
+
+(def ^:private help-text (delay (str "Version: " @version "
You use the Clojure tools ('clj' or 'clojure') to run Clojure programs
on the JVM, e.g. to start a REPL or invoke a specific function with data.
@@ -196,10 +222,10 @@ For more info, see:
https://clojure.org/guides/deps_and_cli
https://clojure.org/reference/repl_and_main")))
-(defn describe-line [[kw val]]
+(defn- describe-line [[kw val]]
(pr kw val))
-(defn describe [lines]
+(defn- describe [lines]
(let [[first-line & lines] lines]
(print "{") (describe-line first-line)
(doseq [line lines
@@ -207,12 +233,12 @@ For more info, see:
(print "\n ") (describe-line line))
(println "}")))
-(defn ^:private ^:dynamic *getenv-fn*
- "Get ENV'ironment variable."
+(defn- ^:dynamic *getenv-fn*
+ "Get ENV'ironment variable. Only used for testing, not part of the public API (yet)."
^String [env]
(java.lang.System/getenv env))
-(defn cksum
+(defn- cksum
[^String s]
(let [hashed (.digest (java.security.MessageDigest/getInstance "MD5")
(.getBytes s))
@@ -222,7 +248,7 @@ For more info, see:
(print (format "%02X" byte))))
(str sw)))
-(defn which [executable]
+(defn- which [executable]
(when-let [path (*getenv-fn* "PATH")]
(let [paths (.split path path-separator)]
(loop [paths paths]
@@ -233,13 +259,13 @@ For more info, see:
(.getCanonicalPath f)
(recur (rest paths)))))))))
-(defn home-dir []
+(defn- home-dir []
(if windows?
;; workaround for https://github.com/oracle/graal/issues/1630
(*getenv-fn* "userprofile")
(System/getProperty "user.home")))
-(def java-exe (if windows? "java.exe" "java"))
+(def ^:private java-exe (if windows? "java.exe" "java"))
(defn- get-java-cmd
"Returns path to java executable to invoke sub commands with."
@@ -260,11 +286,11 @@ For more info, see:
(def ^:private authenticated-proxy-re #".+:.+@(.+):(\d+).*")
(def ^:private unauthenticated-proxy-re #"(.+):(\d+).*")
-(defn proxy-info [m]
+(defn- proxy-info [m]
{:host (nth m 1)
:port (nth m 2)})
-(defn parse-proxy-info
+(defn- parse-proxy-info
[s]
(when s
(let [p (cond
@@ -285,14 +311,14 @@ For more info, see:
(do (warn "WARNING: Can't parse proxy info - found:" s "- proceeding without using proxy!")
nil)))))
-(defn env-proxy-info
+(defn get-proxy-info
"Returns a map with proxy information parsed from env vars. The map
will contain :http-proxy and :https-proxy entries if the relevant
env vars are set and parsed correctly. The value for each is a map
with :host and :port entries."
[]
- (let [http-proxy (parse-proxy-info (or (*getenv-fn* "http_proxy")
- (*getenv-fn* "HTTP_PROXY")))
+ (let [http-proxy (parse-proxy-info (or (*getenv-fn* "http_proxy")
+ (*getenv-fn* "HTTP_PROXY")))
https-proxy (parse-proxy-info (or (*getenv-fn* "https_proxy")
(*getenv-fn* "HTTPS_PROXY")))]
(cond-> {}
@@ -302,22 +328,20 @@ For more info, see:
(defn set-proxy-system-props!
"Sets the proxy system properties in the current JVM.
proxy-info parameter is as returned from env-proxy-info."
- [proxy-info]
- (let [{:keys [http-proxy https-proxy]} proxy-info]
- (when http-proxy
- (System/setProperty "http.proxyHost" (:host http-proxy))
- (System/setProperty "http.proxyPort" (:port http-proxy)))
- (when https-proxy
- (System/setProperty "https.proxyHost" (:host https-proxy))
- (System/setProperty "https.proxyPort" (:port https-proxy)))))
-
-
-(defn clojure-tools-download-direct
- "Downloads from SOURCE url to DEST file returning true on success."
- [source dest]
+ [{:keys [http-proxy https-proxy]}]
+ (when http-proxy
+ (System/setProperty "http.proxyHost" (:host http-proxy))
+ (System/setProperty "http.proxyPort" (:port http-proxy)))
+ (when https-proxy
+ (System/setProperty "https.proxyHost" (:host https-proxy))
+ (System/setProperty "https.proxyPort" (:port https-proxy))))
+
+(defn clojure-tools-download-direct!
+ "Downloads from `:url` to `:dest` file returning true on success."
+ [{:keys [url dest]}]
(try
- (set-proxy-system-props! (env-proxy-info))
- (let [source (URL. source)
+ (set-proxy-system-props! (get-proxy-info))
+ (let [source (URL. url)
dest (io/file dest)
conn ^URLConnection (.openConnection ^URL source)]
(when (instance? HttpURLConnection conn)
@@ -349,14 +373,14 @@ For more info, see:
:ct-zip-name The file name to store the archive as."
(delay (let [version @version]
- {:ct-base-dir "ClojureTools"
+ {:ct-base-dir "ClojureTools"
:ct-error-exit-code 99
:ct-aux-files-names ["exec.jar" "example-deps.edn" "tools.edn"]
:ct-jar-name (format "clojure-tools-%s.jar" version)
:ct-url-str (format "https://download.clojure.org/install/clojure-tools-%s.zip" version)
:ct-zip-name "tools.zip"})))
-(defn unzip
+(defn- unzip
[zip-file destination-dir]
(let [{:keys [ct-aux-files-names ct-jar-name]} @clojure-tools-info*
zip-file (io/file zip-file)
@@ -366,8 +390,8 @@ For more info, see:
zip-file (.toPath zip-file)
files (into #{ct-jar-name} ct-aux-files-names)]
(with-open
- [fis (Files/newInputStream zip-file (into-array java.nio.file.OpenOption []))
- zis (ZipInputStream. fis)]
+ [fis (Files/newInputStream zip-file (into-array java.nio.file.OpenOption []))
+ zis (ZipInputStream. fis)]
(loop []
(when-let [entry (.getNextEntry zis)]
(let [entry-name (.getName entry)
@@ -419,93 +443,92 @@ public class ClojureToolsDownloader {
System.exit(1); }}}"))
dest-file))
-(defn- clojure-tools-download-java
- "Downloads URL file to DEST-ZIP-FILE by invoking `java` with JVM-OPTS
- on a `.java` program file, and returns true on success. Requires
- Java 11+ (JEP 330)."
- [url dest-zip-file jvm-opts]
- (let [dest-dir (.getCanonicalPath (io/file dest-zip-file ".."))
+(defn proxy-jvm-opts
+ "Returns a vector containing the JVM system property arguments to be passed to a new process
+ to set its proxy system properties.
+ proxy-info parameter is as returned from env-proxy-info."
+ [{:keys [http-proxy https-proxy]}]
+ (cond-> []
+ http-proxy (concat [(str "-Dhttp.proxyHost=" (:host http-proxy))
+ (str "-Dhttp.proxyPort=" (:port http-proxy))])
+ https-proxy (concat [(str "-Dhttps.proxyHost=" (:host https-proxy))
+ (str "-Dhttps.proxyPort=" (:port https-proxy))])))
+
+(defn clojure-tools-download-java!
+ "Downloads `:url` zip file to `:dest` by invoking `java` with
+ `:proxy` options on a `.java` program file, and returns true on
+ success. Requires Java 11+ (JEP 330)."
+ [{:keys [url dest proxy-opts clj-jvm-opts]}]
+ (let [dest-dir (.getCanonicalPath (io/file dest ".."))
dlr-path (clojure-tools-java-downloader-spit dest-dir)
java-cmd [(get-java-cmd) "-XX:-OmitStackTraceInFastThrow"]
success?* (atom true)]
- (binding [*exit-fn* (fn
- ([exit-code] (when-not (= exit-code 0) (reset! success?* false)))
- ([exit-code msg] (when-not (= exit-code 0)
- (warn msg)
- (reset! success?* false))))]
- (shell-command (vec (concat java-cmd
- jvm-opts
- [dlr-path url (str dest-zip-file)])))
+ (binding [*exit-fn* (fn [{:keys [exit message]}]
+ (when-not (= exit 0)
+ (warn message)
+ (reset! success?* false)))]
+ (*aux-process-fn* {:cmd (vec (concat java-cmd
+ clj-jvm-opts
+ (proxy-jvm-opts proxy-opts)
+ [dlr-path url (str dest)]))})
(io/delete-file dlr-path true)
@success?*)))
-(def ^:private ^:dynamic *custom-clojure-tool-downloader*
+(def ^:dynamic *clojure-tools-download-fn*
"Can be dynamically rebound to customise the download of the Clojure tools.
- Should be bound to a function accepting three parameters:
- - The URL to download, as a string
- - The path to the file to download it to, as a string
- - a proxy info structure, as returned by env-proxy-info
- Should return true if the download was successful, or false if not."
+ Should be bound to a function accepting a map with:
+ - `:url`: The URL to download, as a string
+ - `:dest`: The path to the file to download it to, as a string
+ - `:proxy-opts`: a map as returned by `get-proxy-info`
+ - `:clj-jvm-opts`: a vector of JVM opts (as passed on the command line).
+ Should return true if the `download` was successful, or false if not."
nil)
-
-(defn clojure-tools-jar-download
- "Downloads clojure tools archive in OUT-DIR, if not already there,
+(defn clojure-tools-download!
+ "Downloads clojure tools archive in `:out-dir`, if not already there,
and extracts in-place the clojure tools jar file and other important
files.
The download is attempted directly from this process, unless
- JAVA-ARGS-WITH-CLJ-JVM-OPTS is set, in which case a java subprocess
+ `:jvm-opts` is set, in which case a java subprocess
is created to download the archive passing in its value as command
line options.
It calls `*exit-fn*` if it cannot download the archive, with
instructions how to manually download it."
- [out-dir java-args-with-clj-jvm-opts {:keys [debug] :as _opts}]
+ [{:keys [out-dir debug proxy-opts clj-jvm-opts]}]
(let [{:keys [ct-error-exit-code ct-url-str ct-zip-name]} @clojure-tools-info*
dir (io/file out-dir)
zip-file (io/file out-dir ct-zip-name)]
(when-not (.exists zip-file)
(warn "Downloading" ct-url-str "to" (str zip-file))
(.mkdirs dir)
- (or (when *custom-clojure-tool-downloader*
+ (or (when *clojure-tools-download-fn*
(when debug (warn "Attempting download using custom download function..."))
- (*custom-clojure-tool-downloader* ct-url-str (str zip-file) (env-proxy-info)))
- (when java-args-with-clj-jvm-opts
+ (*clojure-tools-download-fn* {:url ct-url-str :dest (str zip-file) :proxy-opts proxy-opts :clj-jvm-opts clj-jvm-opts}))
+ (when (seq clj-jvm-opts)
(when debug (warn "Attempting download using java subprocess... (requires Java11+)"))
- (clojure-tools-download-java ct-url-str (str zip-file) java-args-with-clj-jvm-opts))
+ (clojure-tools-download-java! {:url ct-url-str :dest (str zip-file) :proxy-opts proxy-opts :clj-jvm-opts clj-jvm-opts}))
(do (when debug (warn "Attempting direct download..."))
- (clojure-tools-download-direct ct-url-str zip-file))
- (*exit-fn* ct-error-exit-code (str "Error: Cannot download Clojure tools."
- " Please download manually from " ct-url-str
- " to " (str (io/file dir ct-zip-name))))
- {:url ct-url-str :dest-dir (str dir)}))
+ (clojure-tools-download-direct! {:url ct-url-str :dest zip-file}))
+ (*exit-fn* {:exit ct-error-exit-code
+ :message (str "Error: Cannot download Clojure tools."
+ " Please download manually from " ct-url-str
+ " to " (str (io/file dir ct-zip-name)))})
+ {:url ct-url-str :out-dir (str dir)}))
(warn "Unzipping" (str zip-file) "...")
(unzip zip-file (.getPath dir))
(.delete zip-file))
(warn "Successfully installed clojure tools!"))
-(defn jvm-proxy-settings
- "Returns a vector containing the JVM args to be passed to a new process
- to set its proxy system properties.
- proxy-info parameter is as returned from env-proxy-info."
- [proxy-info]
- (let [{:keys [http-proxy https-proxy]} proxy-info]
- (cond-> []
- http-proxy (concat [(str "-Dhttp.proxyHost=" (:host http-proxy))
- (str "-Dhttp.proxyPort=" (:port http-proxy))])
- https-proxy (concat [(str "-Dhttps.proxyHost=" (:host https-proxy))
- (str "-Dhttps.proxyPort=" (:port https-proxy))]))))
-
-(def parse-opts->keyword
+(def ^:private parse-opts->keyword
{"-J" :jvm-opts
"-R" :resolve-aliases
"-C" :classpath-aliases
- "-A" :repl-aliases
- })
+ "-A" :repl-aliases})
-(def bool-opts->keyword
+(def ^:private bool-opts->keyword
{"-Spath" :print-classpath
"-Sverbose" :verbose
"-Strace" :trace
@@ -516,20 +539,22 @@ public class ClojureToolsDownloader {
"-Spom" :pom
"-P" :prep})
-(def string-opts->keyword
+(def ^:private string-opts->keyword
{"-Sdeps" :deps-data
"-Scp" :force-cp
"-Sdeps-file" :deps-file
"-Scommand" :command
"-Sthreads" :threads})
-(defn non-blank [s]
+(defn ^:private non-blank [s]
(when-not (str/blank? s)
s))
-(def vconj (fnil conj []))
+(def ^:private vconj (fnil conj []))
-(defn parse-args [args]
+(defn parse-cli-opts
+ "Parses the command line options."
+ [args]
(loop [args (seq args)
acc {:mode :repl}]
(if args
@@ -569,17 +594,17 @@ public class ClojureToolsDownloader {
;; deprecations
(some #(str/starts-with? arg %) ["-R" "-C"])
(do (warn arg "-R is no longer supported, use -A with repl, -M for main, -X for exec, -T for tool")
- (*exit-fn* 1))
+ (*exit-fn* {:exit 1}))
(some #(str/starts-with? arg %) ["-O"])
(let [msg (str arg " is no longer supported, use -A with repl, -M for main, -X for exec, -T for tool")]
- (*exit-fn* 1 msg))
+ (*exit-fn* {:exit 1 :message msg}))
(= "-Sresolve-tags" arg)
(let [msg "Option changed, use: clj -X:deps git-resolve-tags"]
- (*exit-fn* 1 msg))
+ (*exit-fn* {:exit 1 :message msg}))
;; end deprecations
(= "-A" arg)
(let [msg "-A requires an alias"]
- (*exit-fn* 1 msg))
+ (*exit-fn* {:exit 1 :message msg}))
(some #(str/starts-with? arg %) ["-J" "-C" "-O" "-A"])
(recur (next args)
(update acc (get parse-opts->keyword (subs arg 0 2))
@@ -592,7 +617,7 @@ public class ClojureToolsDownloader {
(assoc acc string-opt-keyword
(second args)))
(str/starts-with? arg "-S") (let [msg (str "Invalid option: " arg)]
- (*exit-fn* 1 msg))
+ (*exit-fn* {:exit 1 :message msg}))
(and
(not (some acc [:main-aliases :all-aliases]))
(or (= "-h" arg)
@@ -606,48 +631,63 @@ public class ClojureToolsDownloader {
(if (instance? Path path) path
(.toPath (io/file path))))
-(defn unixify
+(defn- unixify
^Path [f]
(as-path (if windows?
(-> f as-path .toUri .getPath)
(str f))))
(defn- relativize
- "Returns relative path by comparing this with other. Returns absolute path unchanged."
+ "Returns relative path as string by comparing this with other. Returns
+ absolute path unchanged."
^Path [f]
- (if (.isAbsolute (as-path f))
- f
- (if-let [dir *dir*]
- (str (.relativize (unixify (.toAbsolutePath (as-path dir)))
- (unixify (.toAbsolutePath (as-path f)))))
- f)))
-
-(defn calculate-env-tools-dir []
+ (str (if (.isAbsolute (as-path f))
+ f
+ (if-let [dir *dir*]
+ (.relativize (unixify (.toAbsolutePath (as-path dir)))
+ (unixify (.toAbsolutePath (as-path f))))
+ f))))
+
+(defn- get-env-tools-dir
+ "Retrieves the tools-directory from environment variable `DEPS_CLJ_TOOLS_DIR`"
+ []
(or
;; legacy name
- (*getenv-fn* "CLOJURE_TOOLS_DIR")
- (*getenv-fn* "DEPS_CLJ_TOOLS_DIR")))
+ (*getenv-fn* "CLOJURE_TOOLS_DIR")
+ (*getenv-fn* "DEPS_CLJ_TOOLS_DIR")))
-(defn calculate-tools-dir []
+(defn get-install-dir
+ "Retrieves the install directory where tools jar is located (after download).
+ Defaults to ~/.deps.clj//ClojureTools."
+ []
(let [{:keys [ct-base-dir]} @clojure-tools-info*]
- (or (calculate-env-tools-dir)
+ (or (get-env-tools-dir)
(.getPath (io/file (home-dir)
".deps.clj"
@version
ct-base-dir)))))
-(defn calculate-config-dir []
+(defn get-config-dir
+ "Retrieves configuration directory.
+ First tries `CLJ_CONFIG` env var, then `$XDG_CONFIG_HOME/clojure`, then ~/.clojure."
+ []
(or (*getenv-fn* "CLJ_CONFIG")
(when-let [xdg-config-home (*getenv-fn* "XDG_CONFIG_HOME")]
(.getPath (io/file xdg-config-home "clojure")))
(.getPath (io/file (home-dir) ".clojure"))))
-(defn calculate-deps-edn [opts]
- (or (:deps-file opts)
+(defn get-local-deps-edn
+ "Returns the path of the `deps.edn` file (as string) in the current directory or as set by `-Sdeps-file`.
+ Required options:
+ * `:cli-opts`: command line options as parsed by `parse-opts`"
+ [{:keys [cli-opts]}]
+ (or (:deps-file cli-opts)
(.getPath (io/file *dir* "deps.edn"))))
-(defn calculate-cache-dir [deps-edn config-dir]
- ;; Determine whether to use user or project cache
+(defn get-cache-dir
+ "Returns cache dir (`.cpcache`) from either local dir, if `deps-edn`
+ exists, or the user cache dir."
+ [{:keys [deps-edn config-dir]}]
(let [user-cache-dir
(or (*getenv-fn* "CLJ_CACHE")
(when-let [xdg-config-home (*getenv-fn* "XDG_CACHE_HOME")]
@@ -657,8 +697,13 @@ public class ClojureToolsDownloader {
(.getPath (io/file *dir* ".cpcache"))
user-cache-dir)))
-(defn calculate-config-paths [opts deps-edn config-dir install-dir]
- (if (:repro opts)
+(defn get-config-paths
+ "Returns vec of configuration paths, i.e. deps.edn from:
+ - `:install-dir` as obtained thrhough `get-install-dir`
+ - `:config-dir` as obtained through `get-config-dir`
+ - `:deps-edn` as obtained through `get-local-deps-edn`"
+ [{:keys [cli-opts deps-edn config-dir install-dir]}]
+ (if (:repro cli-opts)
(if install-dir
[(.getPath (io/file install-dir "deps.edn")) deps-edn]
[deps-edn])
@@ -686,6 +731,16 @@ public class ClojureToolsDownloader {
config-paths)))]
(cksum val*)))
+(defn get-help
+ "Returns help text as string."
+ []
+ @help-text)
+
+(defn print-help
+ "Print help text"
+ []
+ (println @help-text))
+
(defn -main
"See `help-text`.
@@ -704,44 +759,42 @@ public class ClojureToolsDownloader {
archive by invoking a java subprocess passing the env variable value
as command line options."
[& command-line-args]
- (let [opts (parse-args command-line-args)
+ (let [cli-opts (parse-cli-opts command-line-args)
{:keys [ct-jar-name]} @clojure-tools-info*
debug (*getenv-fn* "DEPS_CLJ_DEBUG")
java-cmd [(get-java-cmd) "-XX:-OmitStackTraceInFastThrow"]
- env-tools-dir (calculate-env-tools-dir)
- tools-dir (calculate-tools-dir)
- install-dir tools-dir
+ env-tools-dir (get-env-tools-dir)
+ install-dir (get-install-dir)
libexec-dir (if env-tools-dir
(let [f (io/file env-tools-dir "libexec")]
(if (.exists f)
(.getPath f)
env-tools-dir))
- tools-dir)
+ install-dir)
tools-jar (io/file libexec-dir ct-jar-name)
exec-jar (io/file libexec-dir "exec.jar")
- proxy-settings (jvm-proxy-settings (env-proxy-info))
+ proxy-opts (get-proxy-info)
+ proxy-settings (proxy-jvm-opts proxy-opts)
clj-jvm-opts (some-> (*getenv-fn* "CLJ_JVM_OPTS") (str/split #" "))
tools-cp
(or
(when (.exists tools-jar) (.getPath tools-jar))
(binding [*out* *err*]
(warn "Clojure tools not yet in expected location:" (str tools-jar))
- (let [java-clj-jvm-opts (when clj-jvm-opts (vec (concat clj-jvm-opts
- proxy-settings)))]
- (clojure-tools-jar-download libexec-dir java-clj-jvm-opts {:debug debug}))
+ (clojure-tools-download! {:out-dir libexec-dir :debug debug :clj-jvm-opts clj-jvm-opts :proxy-opts proxy-opts})
tools-jar))
- mode (:mode opts)
+ mode (:mode cli-opts)
exec? (= :exec mode)
tool? (= :tool mode)
exec-cp (when (or exec? tool?)
(.getPath exec-jar))
- deps-edn (calculate-deps-edn opts)
+ deps-edn (get-local-deps-edn {:cli-opts cli-opts})
clj-main-cmd
(vec (concat java-cmd
clj-jvm-opts
proxy-settings
["-classpath" tools-cp "clojure.main"]))
- config-dir (calculate-config-dir)
+ config-dir (get-config-dir)
java-opts (some-> (*getenv-fn* "JAVA_OPTS") (str/split #" "))]
;; If user config directory does not exist, create it
(let [config-dir (io/file config-dir)]
@@ -763,21 +816,24 @@ public class ClojureToolsDownloader {
;; Determine user cache directory
(let [;; Chain deps.edn in config paths. repro=skip config dir
config-user
- (when-not (:repro opts)
+ (when-not (:repro cli-opts)
(.getPath (io/file config-dir "deps.edn")))
config-project deps-edn
- config-paths (calculate-config-paths opts deps-edn config-dir install-dir)
- cache-dir (calculate-cache-dir deps-edn config-dir)
+ config-paths (get-config-paths {:cli-opts cli-opts
+ :deps-edn deps-edn
+ :config-dir config-dir
+ :install-dir install-dir})
+ cache-dir (get-cache-dir {:deps-edn deps-edn :config-dir config-dir})
;; Construct location of cached classpath file
- tool-name (:tool-name opts)
- tool-aliases (:tool-aliases opts)
- ck (calculate-checksum opts config-paths)
+ tool-name (:tool-name cli-opts)
+ tool-aliases (:tool-aliases cli-opts)
+ ck (calculate-checksum cli-opts config-paths)
cp-file (.getPath (io/file cache-dir (str ck ".cp")))
jvm-file (.getPath (io/file cache-dir (str ck ".jvm")))
main-file (.getPath (io/file cache-dir (str ck ".main")))
basis-file (.getPath (io/file cache-dir (str ck ".basis")))
manifest-file (.getPath (io/file cache-dir (str ck ".manifest")))
- _ (when (:verbose opts)
+ _ (when (:verbose cli-opts)
(println "deps.clj version =" deps-clj-version)
(println "version =" @version)
(when install-dir (println "install_dir =" install-dir))
@@ -786,14 +842,14 @@ public class ClojureToolsDownloader {
(println "cache_dir =" cache-dir)
(println "cp_file =" cp-file)
(println))
- tree? (:tree opts)
+ tree? (:tree cli-opts)
;; Check for stale classpath file
cp-file (io/file cp-file)
stale
- (or (:force opts)
- (:trace opts)
+ (or (:force cli-opts)
+ (:trace cli-opts)
tree?
- (:prep opts)
+ (:prep cli-opts)
(not (.exists cp-file))
(when tool-name
(let [tool-file (io/file config-dir "tools" (str tool-name ".edn"))]
@@ -821,67 +877,68 @@ public class ClojureToolsDownloader {
(not (.exists (io/file entry)))))
entries)))
tools-args
- (when (or stale (:pom opts))
+ (when (or stale (:pom cli-opts))
(cond-> []
- (not (str/blank? (:deps-data opts)))
- (conj "--config-data" (:deps-data opts))
- (:main-aliases opts)
- (conj (str "-M" (:main-aliases opts)))
- (:repl-aliases opts)
- (conj (str "-A" (str/join "" (:repl-aliases opts))))
- (:exec-aliases opts)
- (conj (str "-X" (:exec-aliases opts)))
+ (not (str/blank? (:deps-data cli-opts)))
+ (conj "--config-data" (:deps-data cli-opts))
+ (:main-aliases cli-opts)
+ (conj (str "-M" (:main-aliases cli-opts)))
+ (:repl-aliases cli-opts)
+ (conj (str "-A" (str/join "" (:repl-aliases cli-opts))))
+ (:exec-aliases cli-opts)
+ (conj (str "-X" (:exec-aliases cli-opts)))
tool?
(conj "--tool-mode")
tool-name
(conj "--tool-name" tool-name)
tool-aliases
(conj (str "-T" tool-aliases))
- (:force-cp opts)
+ (:force-cp cli-opts)
(conj "--skip-cp")
- (:threads opts)
- (conj "--threads" (:threads opts))
- (:trace opts)
+ (:threads cli-opts)
+ (conj "--threads" (:threads cli-opts))
+ (:trace cli-opts)
(conj "--trace")
tree?
(conj "--tree")))
- classpath-not-needed? (boolean (some #(% opts) [:describe :help :version]))]
+ classpath-not-needed? (boolean (some #(% cli-opts) [:describe :help :version]))]
;; If stale, run make-classpath to refresh cached classpath
(when (and stale (not classpath-not-needed?))
- (when (:verbose opts)
+ (when (:verbose cli-opts)
(warn "Refreshing classpath"))
- (let [res (shell-command (into clj-main-cmd
- (concat
- ["-m" "clojure.tools.deps.script.make-classpath2"
- "--config-user" config-user
- "--config-project" (relativize config-project)
- "--basis-file" (relativize basis-file)
- "--cp-file" (relativize cp-file)
- "--jvm-file" (relativize jvm-file)
- "--main-file" (relativize main-file)
- "--manifest-file" (relativize manifest-file)]
- tools-args))
- {:to-string? tree?})]
+ (let [{:keys [out]} (*aux-process-fn* {:cmd (into clj-main-cmd
+ (concat
+ ["-m" "clojure.tools.deps.script.make-classpath2"
+ "--config-user" config-user
+ "--config-project" (relativize config-project)
+ "--basis-file" (relativize basis-file)
+ "--cp-file" (relativize cp-file)
+ "--jvm-file" (relativize jvm-file)
+ "--main-file" (relativize main-file)
+ "--manifest-file" (relativize manifest-file)]
+ tools-args))
+ :out (when tree?
+ :string)})]
(when tree?
- (print res) (flush))))
+ (print out) (flush))))
(let [cp (cond (or classpath-not-needed?
- (:prep opts)) nil
- (not (str/blank? (:force-cp opts))) (:force-cp opts)
+ (:prep cli-opts)) nil
+ (not (str/blank? (:force-cp cli-opts))) (:force-cp cli-opts)
:else (slurp cp-file))]
- (cond (:help opts) (do (println @help-text)
- (*exit-fn* 0))
- (:version opts) (do (println "Clojure CLI version (deps.clj)" @version)
- (*exit-fn* 0))
- (:prep opts) (*exit-fn* 0)
- (:pom opts)
- (shell-command (into clj-main-cmd
- ["-m" "clojure.tools.deps.script.generate-manifest2"
- "--config-user" config-user
- "--config-project" (relativize config-project)
- "--gen=pom" (str/join " " tools-args)]))
- (:print-classpath opts)
+ (cond (:help cli-opts) (do (print-help)
+ (*exit-fn* {:exit 0}))
+ (:version cli-opts) (do (println "Clojure CLI version (deps.clj)" @version)
+ (*exit-fn* {:exit 0}))
+ (:prep cli-opts) (*exit-fn* {:exit 0})
+ (:pom cli-opts)
+ (*aux-process-fn* {:cmd (into clj-main-cmd
+ ["-m" "clojure.tools.deps.script.generate-manifest2"
+ "--config-user" config-user
+ "--config-project" (relativize config-project)
+ "--gen=pom" (str/join " " tools-args)])})
+ (:print-classpath cli-opts)
(println cp)
- (:describe opts)
+ (:describe cli-opts)
(describe [[:deps-clj-version deps-clj-version]
[:version @version]
[:config-files (filterv #(.exists (io/file %)) config-paths)]
@@ -890,22 +947,22 @@ public class ClojureToolsDownloader {
(when install-dir [:install-dir install-dir])
[:config-dir config-dir]
[:cache-dir cache-dir]
- [:force (boolean (:force opts))]
- [:repro (boolean (:repro opts))]
- [:main-aliases (str (:main-aliases opts))]
- [:all-aliases (str (:all-aliases opts))]])
- tree? (*exit-fn* 0)
- (:trace opts)
+ [:force (boolean (:force cli-opts))]
+ [:repro (boolean (:repro cli-opts))]
+ [:main-aliases (str (:main-aliases cli-opts))]
+ [:all-aliases (str (:all-aliases cli-opts))]])
+ tree? (*exit-fn* {:exit 0})
+ (:trace cli-opts)
(warn "Wrote trace.edn")
- (:command opts)
- (let [command (str/replace (:command opts) "{{classpath}}" (str cp))
+ (:command cli-opts)
+ (let [command (str/replace (:command cli-opts) "{{classpath}}" (str cp))
main-cache-opts (when (.exists (io/file main-file))
(-> main-file slurp str/split-lines))
main-cache-opts (str/join " " main-cache-opts)
command (str/replace command "{{main-opts}}" (str main-cache-opts))
command (str/split command #"\s+")
- command (into command (:args opts))]
- (*process-fn* command))
+ command (into command (:args cli-opts))]
+ (*clojure-process-fn* {:cmd command}))
:else
(let [jvm-cache-opts (when (.exists (io/file jvm-file))
(-> jvm-file slurp str/split-lines))
@@ -921,14 +978,14 @@ public class ClojureToolsDownloader {
java-opts
proxy-settings
jvm-cache-opts
- (:jvm-opts opts)
+ (:jvm-opts cli-opts)
[(str "-Dclojure.basis=" (relativize basis-file))
"-classpath" cp
"clojure.main"]
main-opts)
main-args (filterv some? main-args)
- main-args (into main-args (:args opts))]
+ main-args (into main-args (:args cli-opts))]
(when (and (= :repl mode)
- (pos? (count (:args opts))))
+ (pos? (count (:args cli-opts))))
(warn "WARNING: Implicit use of clojure.main with options is deprecated, use -M"))
- (*process-fn* main-args)))))))
+ (*clojure-process-fn* {:cmd main-args})))))))
diff --git a/test/borkdude/deps_test.clj b/test/borkdude/deps_test.clj
index 9f0f3c1..5c712fb 100644
--- a/test/borkdude/deps_test.clj
+++ b/test/borkdude/deps_test.clj
@@ -5,10 +5,9 @@
[borkdude.deps :as deps]
[clojure.edn :as edn]
[clojure.java.io :as io]
+ [clojure.set :as set]
[clojure.string :as str]
- [clojure.test :as t :refer [deftest is testing]]
- [clojure.set :as set])
-
+ [clojure.test :as t :refer [deftest is testing]])
(:import [java.util.zip ZipEntry ZipOutputStream]))
;; Print out information about the java executable that will be used
@@ -33,22 +32,22 @@
[& args]
(case (or (System/getenv "DEPS_CLJ_TEST_ENV") "clojure")
- "babashka" (let [classpath (str/join deps/path-separator ["src" "test" "resources"])]
+ "babashka" (let [classpath (str/join @#'deps/path-separator ["src" "test" "resources"])]
(apply str "bb -cp " classpath " -m borkdude.deps " args))
"native" (apply str "./deps " args)
"clojure" (cond->>
- (apply str "clojure -M -m borkdude.deps " args)
- deps/windows?
+ (apply str "clojure -M -m borkdude.deps " args)
+ @#'deps/windows?
;; the `exit` command is a workaround for
;; https://ask.clojure.org/index.php/12290/clojuretools-commands-windows-properly-exit-code-failure
(format "powershell -NoProfile -Command %s; exit $LASTEXITCODE"))))
-(deftest parse-args-test
+(deftest parse-cli-opts-test
(is (= {:mode :repl, :jvm-opts ["-Dfoo=bar" "-Dbaz=quuz"]}
- (deps/parse-args ["-J-Dfoo=bar" "-J-Dbaz=quuz"])))
+ (deps/parse-cli-opts ["-J-Dfoo=bar" "-J-Dbaz=quuz"])))
(is (= {:mode :main, :main-aliases nil, :args '("-e" "(+ 1 2 3)")}
- (deps/parse-args ["-M" "-e" "(+ 1 2 3)"])))
- (is (= {:mode :main, :main-aliases ":foo", :args nil} (deps/parse-args ["-M:foo"]))))
+ (deps/parse-cli-opts ["-M" "-e" "(+ 1 2 3)"])))
+ (is (= {:mode :main, :main-aliases ":foo", :args nil} (deps/parse-cli-opts ["-M:foo"]))))
(deftest path-test
(is (str/includes? (with-out-str
@@ -85,11 +84,10 @@
:msg The process's error messsage (if any)."
[& command-line-args]
`(binding [deps/*exit-fn*
- (fn
- ([exit-code#] (when-not (= exit-code# 0)
- (throw (ex-info (str ::deps-main-throw) {:exit-code exit-code#}))))
- ([exit-code# msg#] (throw (ex-info (str ::deps-main-throw)
- {:exit-code exit-code# :msg msg#}))))]
+ (fn [{:keys [~'exit ~'message]}]
+ (when ~'message
+ (throw (ex-info (str ::deps-main-throw)
+ {:exit-code ~'exit :msg ~'message}))))]
(deps/-main ~@command-line-args)))
(deftest whitespace-test
@@ -108,7 +106,7 @@
temp-file-path (str temp-file)
_ (deps-main-throw "-Sdeps"
(format
- (if-not deps/windows?
+ (if-not @#'deps/windows?
"{:aliases {:space {:main-opts [\"-e\" \"(spit \\\"%s\\\" (+ 1 2 3))\"]}}}"
"{:aliases {:space {:main-opts [\"-e\" \"(spit \\\\\"%s\\\\\" (+ 1 2 3))\"]}}}")
(.toURI (fs/file temp-file-path)))
@@ -117,29 +115,29 @@
(is (= "6" out)))))
(deftest jvm-proxy-settings-test
- (is (= {:host "aHost" :port "1234"} (deps/parse-proxy-info "http://aHost:1234")))
- (is (= {:host "aHost" :port "1234"} (deps/parse-proxy-info "http://user:pw@aHost:1234")))
- (is (= {:host "aHost" :port "1234"} (deps/parse-proxy-info "https://aHost:1234")))
- (is (= {:host "aHost" :port "1234"} (deps/parse-proxy-info "https://user:pw@aHost:1234")))
- (is (nil? (deps/parse-proxy-info "http://aHost:abc")))
+ (is (= {:host "aHost" :port "1234"} (#'deps/parse-proxy-info "http://aHost:1234")))
+ (is (= {:host "aHost" :port "1234"} (#'deps/parse-proxy-info "http://user:pw@aHost:1234")))
+ (is (= {:host "aHost" :port "1234"} (#'deps/parse-proxy-info "https://aHost:1234")))
+ (is (= {:host "aHost" :port "1234"} (#'deps/parse-proxy-info "https://user:pw@aHost:1234")))
+ (is (nil? (#'deps/parse-proxy-info "http://aHost:abc")))
(is (= {:http-proxy {:host "aHost" :port "1234"}}
(binding [deps/*getenv-fn* {"http_proxy" "http://aHost:1234"}]
- (deps/env-proxy-info))))
+ (deps/get-proxy-info))))
(is (= {:http-proxy {:host "aHost" :port "1234"}}
(binding [deps/*getenv-fn* {"HTTP_PROXY" "http://aHost:1234"}]
- (deps/env-proxy-info))))
+ (deps/get-proxy-info))))
(is (= {:https-proxy {:host "aHost" :port "1234"}}
(binding [deps/*getenv-fn* {"https_proxy" "http://aHost:1234"}]
- (deps/env-proxy-info))))
+ (deps/get-proxy-info))))
(is (= {:https-proxy {:host "aHost" :port "1234"}}
(binding [deps/*getenv-fn* {"HTTPS_PROXY" "http://aHost:1234"}]
- (deps/env-proxy-info))))
+ (deps/get-proxy-info))))
(is (= {}
(binding [deps/*getenv-fn* {}]
- (deps/env-proxy-info))))
+ (deps/get-proxy-info))))
(is (= {}
(binding [deps/*getenv-fn* {"http_proxy" "http://aHost:abc"}]
- (deps/env-proxy-info)))))
+ (deps/get-proxy-info)))))
(deftest jvm-opts-test
(let [temp-dir (fs/create-temp-dir)
@@ -149,7 +147,7 @@
"-M" "-e" (format "
(spit \"%s\" (pr-str [(System/getProperty \"foo\") (System/getProperty \"baz\")]))"
(.toURI (fs/file temp-file-path))))
- (is (= ["bar" "quux"] (edn/read-string (slurp temp-file-path))))))
+ (is (= ["bar" "quux"] (edn/read-string (slurp temp-file-path))))))
(deftest tools-dir-env-test
(fs/delete-tree "tools-dir")
@@ -207,8 +205,8 @@
program, but throws an exception in case of error while is still in
the `babashka.deps` scope."
[env-vars & body]
- (let [body-str (pr-str body)]
- `(let [shell-command# deps/shell-command
+ (let [body-str (pr-str body)]
+ `(let [shell-command# @#'deps/internal-shell-command
ret*# (promise)
sh-mock# (fn mock#
([args#]
@@ -218,17 +216,18 @@
(deliver ret*# args#)
ret#)))]
;; need to override both *process-fn* and deps/shell-command.
- (binding [deps/*process-fn* sh-mock#
- deps/*exit-fn* (fn
- ([exit-code#] (when-not (= exit-code# 0)
- (throw (ex-info "mock-shell-failed" {:exit-code exit-code#}))))
- ([exit-code# msg#] (throw (ex-info "mock-shell-failed"
- {:exit-code exit-code# :msg msg#}))))
+ (binding [deps/*clojure-process-fn* (fn ~'[{:keys [cmd]}]
+ (sh-mock# ~'cmd))
+ deps/*aux-process-fn* (fn ~'[{:keys [cmd out]}]
+ (sh-mock# ~'cmd {:to-string? (= :string ~'out)}))
+ deps/*exit-fn* (fn [{:keys [~'exit ~'message]}]
+ (when ~'message
+ (throw (ex-info "mock-shell-failed"
+ {:exit-code ~'exit :msg ~'message}))))
deps/*getenv-fn* #(or (get ~env-vars %)
(System/getenv %))]
- (with-redefs [deps/shell-command sh-mock#]
- ~@body
- (or (deref ret*# 500 false) (ex-info "No shell-command invoked in body." {:body ~body-str})))))))
+ ~@body
+ (or (deref ret*# 500 false) (ex-info "No shell-command invoked in body." {:body ~body-str}))))))
(defn java-major-version-get
"Returns the major version number of the java executable used to run
@@ -249,7 +248,7 @@
(let [{:keys [ct-base-dir ct-aux-files-names ct-jar-name]} @@#'deps/clojure-tools-info*
file (io/file out-dir "borkdude-deps-test-dummy-tools.zip")]
(with-open [os (io/output-stream file)
- zip (ZipOutputStream. os)]
+ zip (ZipOutputStream. os)]
(doseq [entry (into [ct-jar-name] ct-aux-files-names)]
(doto zip
(.putNextEntry (ZipEntry. (str ct-base-dir "/" entry)))
@@ -274,10 +273,10 @@
dest-zip-file (fs/file temp-dir ct-zip-name)]
(if (< java-version 11)
;; requires java11+, fails otherwise
- (do (is (= false (#'deps/clojure-tools-download-java url dest-zip-file [])))
+ (do (is (= false (#'deps/clojure-tools-download-java! {:url url :dest dest-zip-file})))
(is (not (fs/exists? dest-zip-file))))
- (do (is (= true (#'deps/clojure-tools-download-java url dest-zip-file [])))
+ (do (is (= true (#'deps/clojure-tools-download-java! {:url url :dest dest-zip-file})))
(is (fs/exists? dest-zip-file)))))))
(when (>= java-version 11)
@@ -285,7 +284,7 @@
(fs/with-temp-dir
[temp-dir {}]
(let [dest-jar-file (fs/file temp-dir ct-jar-name)]
- (with-redefs [deps/clojure-tools-download-direct
+ (with-redefs [deps/clojure-tools-download-direct!
(fn [& _] (throw (Exception. "Direct should not be called.")))]
(let [xx-pclf "-XX:+PrintCommandLineFlags"
xx-gc-threads "-XX:ConcGCThreads=1"
@@ -303,14 +302,14 @@
[temp-dir {}]
(let [url-str ct-url-str
dest-zip-file (fs/file temp-dir ct-zip-name)]
- (is (= true (deps/clojure-tools-download-direct url-str dest-zip-file)))
+ (is (= true (deps/clojure-tools-download-direct! {:url url-str :dest dest-zip-file})))
(is (fs/exists? dest-zip-file)))))
(testing "direct downloader called from -main (CLJ_JVM_OPTS not set)"
(fs/with-temp-dir
[temp-dir {}]
(let [dest-jar-file (fs/file temp-dir ct-jar-name)]
- (with-redefs [deps/clojure-tools-download-java
+ (with-redefs [deps/clojure-tools-download-java!
(fn [& _] (throw (Exception. "Java subprocess should not be called.")))]
(binding [deps/*getenv-fn* #(or (get {"DEPS_CLJ_TOOLS_DIR" (str temp-dir)
"CLJ_JVM_OPTS" nil} %)
@@ -326,9 +325,9 @@
dest-zip-file (fs/file temp-dir ct-zip-name)
dest-jar-file (fs/file temp-dir ct-jar-name)]
(fs/copy tools-zip-file dest-zip-file) ;; user copies downloaded file
- (with-redefs [deps/clojure-tools-download-java
+ (with-redefs [deps/clojure-tools-download-java!
(fn [& _] (throw (Exception. "Java should not be called.")))
- deps/clojure-tools-download-direct
+ deps/clojure-tools-download-direct!
(fn [& _] (throw (Exception. "Direct should not be called.")))]
(binding [deps/*getenv-fn* #(or (get {"DEPS_CLJ_TOOLS_DIR" (str temp-dir)} %)
(System/getenv %))]
@@ -340,30 +339,32 @@
(fs/with-temp-dir
[temp-dir {}]
(let [dest-jar-file (fs/file temp-dir ct-jar-name)]
- (with-redefs [deps/clojure-tools-download-java
+ (with-redefs [deps/clojure-tools-download-java!
(fn [& _] (throw (Exception. "Java should not be called.")))
- deps/clojure-tools-download-direct
+ deps/clojure-tools-download-direct!
(fn [& _] (throw (Exception. "Direct should not be called.")))]
(binding [deps/*getenv-fn* #(or (get {"DEPS_CLJ_TOOLS_DIR" (str temp-dir)} %)
(System/getenv %))
- deps/*custom-clojure-tool-downloader*
- (fn [_url dest-path _proxy-info]
+ deps/*clojure-tools-download-fn*
+ (fn [{:keys [url dest] :as opts}]
; Simulate download by creating dummy file and copying to
; specified destination location
+ (is (str/starts-with? url "http"))
+ (is (contains? opts :clj-jvm-opts))
+ (is (contains? opts :proxy-opts))
(let [tools-zip-file (clojure-tools-dummy-zip-file-create (str temp-dir))
- dest-zip-file (fs/file dest-path)]
+ dest-zip-file (fs/file dest)]
(fs/copy tools-zip-file dest-zip-file)
true))]
-
(deps-main-throw "--version")
(is (fs/exists? dest-jar-file)))))))
(testing "prompt for manual user install"
(fs/with-temp-dir
[temp-dir {}]
- (with-redefs [deps/clojure-tools-download-java
+ (with-redefs [deps/clojure-tools-download-java!
(fn [& _] false)
- deps/clojure-tools-download-direct
+ deps/clojure-tools-download-direct!
(fn [& _] false)]
(binding [deps/*getenv-fn* #(or (get {"DEPS_CLJ_TOOLS_DIR" (str temp-dir)} %)
(System/getenv %))]
@@ -424,7 +425,7 @@
(let [deps-map (pr-str '{:mvn/local-repo "test/mvn" :deps {medley/medley {:mvn/version "1.4.0"}
io.github.borkdude/quickblog {:git/sha "8f5898ee911101a96295f59bb5ffc7517757bc8f"}}})
delete #(do (fs/delete-tree (fs/file "test" "mvn"))
- (fs/delete-tree (fs/file (or (some-> (System/getenv "GITLIBS") (fs/file ))
+ (fs/delete-tree (fs/file (or (some-> (System/getenv "GITLIBS") (fs/file))
(fs/file (System/getProperty "user.dir" ".gitlibs")))
"libs" "io.github.borkdude/quickblog" "8f5898ee911101a96295f59bb5ffc7517757bc8f")))
test #(deps/-main "-Sdeps" deps-map "-M" "-e" "(require '[medley.core]) (require '[quickblog.api])")]