From a2966d5967794be815c670f4bcc7dda7df8d0c07 Mon Sep 17 00:00:00 2001 From: Wes Morgan Date: Fri, 7 Oct 2022 10:57:11 -0600 Subject: [PATCH] WIP supporting library-bootstrapped pods Still need to make this work w/ :local/root pod libs and in uberscripts --- src/babashka/impl/classpath.clj | 49 ++++++++++++++++++++++----------- src/babashka/impl/pods.clj | 8 ++++++ src/babashka/main.clj | 37 +++++++++++++++++-------- 3 files changed, 66 insertions(+), 28 deletions(-) diff --git a/src/babashka/impl/classpath.clj b/src/babashka/impl/classpath.clj index 1506b80e..c1875878 100644 --- a/src/babashka/impl/classpath.clj +++ b/src/babashka/impl/classpath.clj @@ -23,20 +23,20 @@ (when (.exists f) (if url? ;; manual conversion, faster than going through .toURI - (java.net.URL. "file" nil (.getAbsolutePath f)) + (URL. "file" nil (.getAbsolutePath f)) {:file (.getAbsolutePath f) :source (slurp f)})))) resource-paths))) (defn path-from-jar - [^java.io.File jar-file resource-paths url?] + [^File jar-file resource-paths url?] (with-open [jar (JarFile. jar-file)] (some (fn [path] (when-let [entry (.getEntry jar path)] (if url? ;; manual conversion, faster than going through .toURI - (java.net.URL. "jar" nil - (str "file:" (.getAbsolutePath jar-file) "!/" path)) + (URL. "jar" nil + (str "file:" (.getAbsolutePath jar-file) "!/" path)) {:file path :source (slurp (.getInputStream jar entry))}))) resource-paths))) @@ -61,19 +61,36 @@ (def path-sep (System/getProperty "path.separator")) -(defn loader [^String classpath] - (let [parts (.split classpath path-sep) - entries (keep part->entry parts)] - (Loader. entries))) +(defn classpath-entries [^String classpath] + (let [parts (.split classpath path-sep)] + (keep part->entry parts))) -(defn source-for-namespace [loader namespace opts] - (let [ns-str (name namespace) - ^String ns-str (munge ns-str) - ;; do NOT pick the platform specific file separator here, since that doesn't work for searching in .jar files - ;; (io/file "foo" "bar/baz") does work on Windows, despite the forward slash - base-path (.replace ns-str "." "/") - resource-paths (mapv #(str base-path %) [".bb" ".clj" ".cljc"])] - (getResource loader resource-paths opts))) +(defn loader [^String classpath] + (Loader. (classpath-entries classpath))) + +(declare get-classpath) + +(defn source-for-namespace + ([namespace opts] + (some-> (get-classpath) loader (source-for-namespace namespace opts))) + ([loader namespace opts] + (let [ns-str (name namespace) + ^String ns-str (munge ns-str) + ;; do NOT pick the platform specific file separator here, since that doesn't work for searching in .jar files + ;; (io/file "foo" "bar/baz") does work on Windows, despite the forward slash + base-path (.replace ns-str "." "/") + manifest-paths (loop [ns (str/split ns-str #"\.") + paths []] + (let [path (str/join "/" (conj ns "pod-manifest.edn")) + next-ns (-> ns butlast vec) + next-paths (conj paths path)] + (if (< 1 (count next-ns)) ; don't look in top-level (e.g. com, pod) namespaces + (recur next-ns next-paths) + next-paths))) + resource-paths (into (mapv #(str base-path %) + [".bb" ".clj" ".cljc"]) + manifest-paths)] + (getResource loader resource-paths opts)))) (defn main-ns [manifest-resource] (with-open [is (io/input-stream manifest-resource)] diff --git a/src/babashka/impl/pods.clj b/src/babashka/impl/pods.clj index 54e7cf22..5f023989 100644 --- a/src/babashka/impl/pods.clj +++ b/src/babashka/impl/pods.clj @@ -32,6 +32,14 @@ "for pods on your local filesystem.")))))) {} pods-map)) +(defn load-pod-from-manifest + [manifest] + (pods/load-pod-from-manifest manifest (-> @bb-edn :file io/file))) + +(defn pod-manifest-file + [manifest] + (pods/pod-manifest-file manifest)) + (def podns (sci/create-ns 'babashka.pods nil)) (def pods-namespace diff --git a/src/babashka/main.clj b/src/babashka/main.clj index 6b19dc77..60a1662e 100644 --- a/src/babashka/main.clj +++ b/src/babashka/main.clj @@ -408,14 +408,14 @@ Use bb run --help to show this help output. (sci/create-ns 'clojure.core.rrb-vector))}) 'edamame.core edamame-namespace 'sci.core {'format-stacktrace (sci/copy-var sci/format-stacktrace sci-ns) - 'stacktrace (sci/copy-var sci/stacktrace sci-ns) + 'stacktrace (sci/copy-var sci/stacktrace sci-ns)} ;; 'eval-string (sci/copy-var sci/eval-string sci-ns) ;; 'eval-string* (sci/copy-var sci/eval-string* sci-ns) ;; 'init (sci/copy-var sci/init sci-ns) ;; 'fork (sci/copy-var sci/fork sci-ns) - } - 'babashka.cli cli/cli-namespace - } + + 'babashka.cli cli/cli-namespace} + features/xml? (assoc 'clojure.data.xml @(resolve 'babashka.impl.xml/xml-namespace) 'clojure.data.xml.event @(resolve 'babashka.impl.xml/xml-event-namespace) 'clojure.data.xml.tree @(resolve 'babashka.impl.xml/xml-tree-namespace)) @@ -843,15 +843,28 @@ Use bb run --help to show this help output. (dissoc (:opts pod) :version :metadata))) {}) - (pods/load-pod (:pod-spec pod) (:opts pod))))) + (do + (pods/load-pod (:pod-spec pod) (:opts pod)) + {})))) (when loader (when-let [res (cp/source-for-namespace loader namespace nil)] - (if uberscript - (do (swap! uberscript-sources conj (:source res)) - (uberscript/uberscript {:ctx @common/ctx - :expressions [(:source res)]}) - {}) - res))) + (println "load-fn source-for-namespace res:" (pr-str res)) + (if (str/ends-with? (:file res) "/pod-manifest.edn") + (let [manifest (-> res :source edn/read-string)] + (when-let [pod-nses (pods/load-pod-from-manifest manifest)] + (println "load-fn got pod namespaces:" (pr-str pod-nses)) + (spit (pods/pod-manifest-file manifest) (:source res)) + (vswap! pod-namespaces merge pod-nses) + (let [pod (get pod-nses namespace)] + (pods/load-pod (:pod-spec pod) (:opts pod))) + {})) + ;; TODO: Figure out how to handle library pods in uberscripts + (if uberscript + (do (swap! uberscript-sources conj (:source res)) + (uberscript/uberscript {:ctx @common/ctx + :expressions [(:source res)]}) + {}) + res)))) (case namespace clojure.spec.alpha (binding [*out* *err*] @@ -887,7 +900,7 @@ Use bb run --help to show this help output. _ (when-let [pods (:pods @common/bb-edn)] (when-let [pod-metadata (pods/load-pods-metadata pods {:download-only (download-only?)})] - (vreset! pod-namespaces pod-metadata))) + (vswap! pod-namespaces merge pod-metadata))) preloads (some-> (System/getenv "BABASHKA_PRELOADS") (str/trim)) [expressions exit-code] (cond expressions [expressions nil]