Skip to content

Instantly share code, notes, and snippets.

@ikappaki
Last active November 28, 2021 23:27
Show Gist options
  • Save ikappaki/ad3a71b235c119dbb920166fd0bc436f to your computer and use it in GitHub Desktop.
Save ikappaki/ad3a71b235c119dbb920166fd0bc436f to your computer and use it in GitHub Desktop.
bb MS-windows ext auto support patch test feedback
(defn which
"Locates a program in (exec-paths) similar to the which Unix command.
On Windows it tries to resolve in the order of: .com, .exe, .bat,
.cmd."
([program] (which program nil))
([program opts]
(let [has-ext? (extension program)]
(loop [paths (babashka.fs/exec-paths)
results []]
(if-let [p (first paths)]
(let [fs (loop [exts (if (and windows? (not has-ext?))
;; :win-exts is unsupported, if you read and use
;; this, let me know, it may break.
(or (:win-exts opts)
[".com" ".exe" ".bat" ".cmd"])
[""])
candidates []]
(if-let [ext (first exts)]
(let [f (babashka.fs/path p (str program ext))]
(if (and (executable? f)
(or (not windows?)
;; on Windows, we require the resolved
;; executable to have an extension, either
;; from the program argument or the result
(extension f)))
(recur (rest exts)
;; (conj candidates f) <- returns Path, need string:
(conj candidates (-> f .toAbsolutePath .toString)))
(recur (rest exts)
candidates)))
candidates))]
(if-let [f (first fs)]
(if (:all opts)
(recur (rest paths) (into results fs))
f)
(recur (rest paths) results)))
(if (:all opts) results (first results)))))))
(ns babashka.impl.tasks-test
(:require [babashka.impl.tasks :as sut]
[babashka.fs :as fs]
[clojure.test :as t]))
;; ....
(defmacro with-exec-paths [paths & body]
`(with-redefs[fs/exec-paths (fn [] ~paths)]
~@body))
(t/deftest shell-playground
(fs/with-temp-dir [tmp-dir {}]
;; create test temp layout
;; tmp-dir
;; |- a/x
;; |- b/x.bat
;; |- c/y.bat
;; |- c/y.bat.bat
;; |- d/z.dev
;; |- d/z.dev.bat
(let [t-a (.getAbsolutePath (fs/file tmp-dir "a"))
t-b (.getAbsolutePath (fs/file tmp-dir "b"))
t-c (.getAbsolutePath (fs/file tmp-dir "c"))
t-d (.getAbsolutePath (fs/file tmp-dir "d"))
t-a-x (.getAbsolutePath (fs/file t-a "x"))
;;t-a-x-cmd (.getAbsolutePath (fs/file t-a "x.cmd"))
t-b-x-bat (.getAbsolutePath (fs/file t-b "x.bat"))
t-c-y-bat (.getAbsolutePath (fs/file t-c "y.bat"))
t-c-y-bat-bat (.getAbsolutePath (fs/file t-c "y.bat.bat"))
t-d-z-dev (.getAbsolutePath (fs/file t-d "z.dev"))
t-d-z-dev-bat (.getAbsolutePath (fs/file t-d "z.dev.bat"))]
(doseq [p [t-a-x t-b-x-bat t-c-y-bat t-c-y-bat-bat
t-d-z-dev t-d-z-dev-bat
;; t-a-x-cmd
]]
(clojure.java.io/make-parents p)
;; add a simple empty comment to the batch file so that can be executed
(spit p "REM"))
(t/testing "solo filename"
(with-exec-paths [t-b]
(let [process (sut/shell "x")]
(t/is (= 0 (:exit process)))))
(with-exec-paths [t-c]
(let [process (sut/shell "y")]
(t/is (= 0 (:exit process)))))
;; fails to find y.bat in the temp c directory
(with-exec-paths [t-c]
(let [process (sut/shell "y.bat")]
(t/is (= 0 (:exit process)))))
;; fails to find z.dev.bat in temp d directory.
(with-exec-paths [t-d]
(let [process (sut/shell "z.dev.bat")]
(t/is (= 0 (:exit process)))))))
))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment