Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 49 additions & 10 deletions clj/src/cljd/build.clj
Original file line number Diff line number Diff line change
Expand Up @@ -840,26 +840,64 @@
(let [digest (.digest (java.security.MessageDigest/getInstance "SHA-256") (.getBytes string "UTF-8"))]
(apply str (map (partial format "%02x") digest))))

(defn find-pubspec [{:keys [:deps/root paths]}]
(defn find-pubspec
"Returns [pubspec-contents base-dir] for a resolved dep, or nil when it has no
pubspec.yaml. `base-dir` is the directory the pubspec's asset/shader paths
resolve against (nil for jar deps, whose files live inside the archive)."
[{:keys [:deps/root paths]}]
(if root
(let [f (java.io.File. root "pubspec.yaml")]
(when (.exists f)
(slurp f)))
[(slurp f) root]))
(some
(fn [path]
(let [f (java.io.File. path)]
(if (.isDirectory f)
(let [f (java.io.File. f "pubspec.yaml")]
(when (.exists f)
(slurp f)))
(let [pf (java.io.File. f "pubspec.yaml")]
(when (.exists pf)
[(slurp pf) path]))
(with-open [in (-> f io/input-stream java.util.jar.JarInputStream.)]
(loop []
(when-some [e (.getNextJarEntry in)]
(if (= "pubspec.yaml" (.getName e))
(slurp in) ; slurp closes `in` but it's ok it's the last action
[(slurp in) nil] ; slurp closes `in` but it's ok it's the last action
(recur))))))))
paths)))

(defn- copy-asset!
"Recursively copies a declared Flutter asset (file or directory) into the stub."
[^java.io.File src ^java.io.File dst]
(cond
(.isDirectory src) (run! #(copy-asset! % (java.io.File. dst (.getName ^java.io.File %)))
(.listFiles src))
(.isFile src) (do (some-> (.getParentFile dst) .mkdirs)
(io/copy src dst))))

(defn- copy-declared-assets!
"Mirrors the `flutter: assets:`/`shaders:`/`fonts:` files a dep's pubspec
declares from its source checkout into the `.clojuredart/deps/<sha>` stub, so
Flutter — which resolves package assets relative to the pubspec's own directory
— can find them. Without this the stub holds only the pubspec and asset/shader
lookups fail at runtime (e.g. FragmentProgram.fromAsset)."
[parser pubspec ^String base-dir ^java.io.File stub-dir]
(when base-dir
(let [flutter (get (.load parser pubspec) "flutter")
;; shaders are plain strings; assets are strings or `{path: ...}` maps;
;; fonts nest as `fonts: [{fonts: [{asset: ...}]}]`
asset->path #(if (instance? java.util.Map %) (get % "path") %)
font-paths (for [family (get flutter "fonts")
font (get family "fonts")]
(get font "asset"))
paths (concat (get flutter "shaders")
(map asset->path (get flutter "assets"))
font-paths)]
(doseq [path paths
:when (string? path)
:let [src (java.io.File. base-dir ^String path)
dst (java.io.File. stub-dir ^String path)]
:when (and (.exists src) (not (.exists dst)))]
(copy-asset! src dst)))))

(defn sync-pubspec! []
(let [parser (org.yaml.snakeyaml.Yaml.)
existing-deps (into {}
Expand All @@ -868,10 +906,10 @@
:when sha]
[[name sha] (-> path java.io.File. .exists)]))
declared-deps (into {}
(for [pubspec (keep find-pubspec (vals (deps/resolve-deps *deps* {})))
(for [[pubspec base-dir] (keep find-pubspec (vals (deps/resolve-deps *deps* {})))
:let [{:strs [name]} (.load parser pubspec)
sha (sha256 pubspec)]]
[[name sha] pubspec]))
[[name sha] {:pubspec pubspec :base-dir base-dir}]))
; the (filter existing-deps) is to remove "bridge" deps which don't exist on disk
; typically when getting an updated pubspec.yaml from scm (git)
deps-to-remove (keys (transduce (filter existing-deps) dissoc existing-deps (keys declared-deps)))
Expand All @@ -884,10 +922,11 @@

(when-some [coords (seq (for [[name sha] (keys deps-to-add)]
(str name ":{\"path\":\".clojuredart/deps/" sha "\"}")))]
(doseq [[[name sha] pubspec] deps-to-add
(doseq [[[name sha] {:keys [pubspec base-dir]}] deps-to-add
:let [f (java.io.File. ".clojuredart/deps" sha)]]
(.mkdirs f)
(spit (java.io.File. f "pubspec.yaml") pubspec))
(spit (java.io.File. f "pubspec.yaml") pubspec)
(copy-declared-assets! parser pubspec base-dir f))
(apply exec {:in nil #_#_:out nil} (some-> *deps* :cljd/opts :kind name) "pub" "add" "--directory=."
coords))))

Expand Down