diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 55e4e2b..65d80b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,7 @@ jobs: test-jvm: strategy: matrix: - java-version: ["11", "17", "21"] + java-version: ["11", "21", "25"] os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} @@ -35,7 +35,6 @@ jobs: - name: Run tests run: | - bb clojure -M:clj-1.9:test -i windows bb clojure -M:clj-1.10:test -i windows bb clojure -M:clj-1.11:test -i windows test-cljs: diff --git a/CHANGELOG.md b/CHANGELOG.md index 7653110..5bc5159 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ For breaking changes, check [here](#breaking-changes). ## Unreleased - [#126](https://github.com/babashka/cli/issues/126): `-` value accidentally parsed as option, e.g. `--file -` +- [#124](https://github.com/babashka/cli/issues/124): Specifying exec fn that starts with hyphen is treated as option +- Drop Clojure 1.9 support. Minimum Clojure version is now 1.10.3. ## v0.8.66 (2025-07-12) diff --git a/src/babashka/cli/exec.clj b/src/babashka/cli/exec.clj index 99c4843..a1372ba 100644 --- a/src/babashka/cli/exec.clj +++ b/src/babashka/cli/exec.clj @@ -9,13 +9,6 @@ (def ^:private ^:dynamic *basis* "For testing" nil) -(defmacro ^:private req-resolve [f] - (if (resolve 'clojure.core/requiring-resolve) - ;; in bb, requiring-resolve must be used in function position currently - `(clojure.core/requiring-resolve ~f) - `(do (require (symbol (namespace ~f))) - (resolve ~f)))) - (defn- resolve-exec-fn [ns-default exec-fn] (if (simple-symbol? exec-fn) (symbol (str ns-default) (str exec-fn)) @@ -47,7 +40,15 @@ (:resolve-args basis)) exec-fn (:exec-fn argmap) ns-default (:ns-default argmap) + first-arg (first args) + [base-args args] (if (and (not exec-fn) + first-arg + (not (str/includes? first-arg "/"))) + (let [base-arg-count (if ns-default 1 2)] + [(take base-arg-count args) (drop base-arg-count args)]) + [nil args]) {:keys [cmds args]} (cli/parse-cmds args) + cmds (concat base-args cmds) [f & cmds] cmds [cli-opts cmds] (cond (not f) nil (str/starts-with? f "{") @@ -66,7 +67,7 @@ unconsumed-args])) args (concat unconsumed-args args) f* f - f (req-resolve f) + f (requiring-resolve f) _ (assert (ifn? f) (str "Could not resolve function: " f*)) ns-opts (:org.babashka/cli (meta (:ns (meta f)))) fn-opts (:org.babashka/cli (meta f)) @@ -81,6 +82,13 @@ opts (parse-opts args opts)] [f opts])) +#_(comment + (System/clearProperty "clojure.basis") + (binding [*basis* nil] + (with-redefs [requiring-resolve identity] + (parse-exec-opts ["dimigi.extraction" "-main" ":a" ":b"]))) + ) + (defn main [& args] (let [[f opts] (parse-exec-opts args)] (set-daemon-agent-executor) diff --git a/test/babashka/cli/exec_test.clj b/test/babashka/cli/exec_test.clj index 52af6fa..4411637 100644 --- a/test/babashka/cli/exec_test.clj +++ b/test/babashka/cli/exec_test.clj @@ -14,6 +14,14 @@ ;; return map argument: m) +(defmacro with-test-env [& body] + `(let [oldbasis# (System/clearProperty "clojure.basis")] + (binding [babashka.cli.exec/*basis* nil] + (with-redefs [requiring-resolve identity] + (try ~@body + (finally (when oldbasis# + (System/setProperty "clojure.basis" oldbasis#)))))))) + (deftest parse-opts-test (System/clearProperty "clojure.basis") ;; this needed to clear the test runner basis (is (submap? {:foo :bar :b 1} (main "babashka.cli.exec-test/foo" ":b" "1"))) @@ -83,5 +91,13 @@ :ns-default babashka.cli.exec-test :exec-fn foo}}] (main ":a" "1" ":b" "2")))))) + (is (= '[dimigi.extraction/-main {:a :b}] + (with-test-env + (#'babashka.cli.exec/parse-exec-opts ["dimigi.extraction" "-main" ":a" ":b"])))) + (is (= '[dimigi.extraction/-main {:a :b}] + (with-test-env + (binding [babashka.cli.exec/*basis* + '{:argmap {:ns-default babashka.cli.exec-test}}]) + (#'babashka.cli.exec/parse-exec-opts ["dimigi.extraction" "-main" ":a" ":b"])))) )