Skip to content

Instantly share code, notes, and snippets.

@micha
Created November 18, 2014 02:06
Show Gist options
  • Select an option

  • Save micha/71c3bdb78e44af029602 to your computer and use it in GitHub Desktop.

Select an option

Save micha/71c3bdb78e44af029602 to your computer and use it in GitHub Desktop.
(ns boot.tmpdir
(:require
[clojure.java.io :as io]
[clojure.set :as set]
[boot.file :as file]))
(defprotocol ITmpFile
(dir [this])
(path [this])
(file [this]))
(defprotocol ITmpFileSet
(user-dirs [this])
(input-dirs [this])
(output-dirs [this])
(user-files [this])
(input-files [this])
(output-files [this])
(add-asset! [this dir])
(add-source! [this dir])
(add-resource! [this dir]))
(defrecord TmpFile [dir path]
ITmpFile
(dir [this] dir)
(path [this] path)
(file [this] (io/file dir path)))
(defrecord TmpDir [dir user input output scoped restored])
(def ^:private masks
{:user {:user true}
:source {:input true :output nil}
:resource {:input true :output true}
:asset {:input nil :output true}
:cache {:input nil :output nil}
:input {:input true}
:output {:output true}
:scoped {:scoped true}
:restored {:restored true}})
(defn- filter-keys
[maps mask]
(->> maps (filter #(= mask (select-keys % (keys mask))))))
(defn- temp-dirs-by
[dirs & masks+]
(->> masks+ (map masks) (apply merge) (filter-keys dirs) (map :dir) set))
(defn- temp-files-for
[dirset]
(->> dirset (mapcat file-seq) (filter (memfn isFile))))
(defn- merge-files!
[tmp-files source-files dest-dir]
(loop [ret tmp-files, [[p f] & fs] (seq source-files)]
(if-not p
ret
(let [tmpf (get ret p)
outf (io/file dest-dir p)]
(file/copy-with-lastmod f outf)
(when tmpf (io/delete-file (file tmpf) true))
(recur (assoc ret p (TmpFile. dest-dir p)) fs)))))
(defn- add-dir!
[fileset mask src-dir]
(let [[out & _] (seq (-> (temp-dirs-by (:dirs fileset) mask)
(set/difference (user-dirs fileset))))
split #(vector (str (file/relative-to %1 %2)) %2)
->files (partial filter (memfn isFile))
file-map #(->> % file-seq ->files (map (partial split %)) (into {}))]
(assoc fileset :files (merge-files! (:files fileset) (file-map src-dir) out))))
(defn- tmp-dir
[dir & masks+]
(-> (->> masks+ (map masks) (apply merge)) (assoc :dir dir) map->TmpDir))
(defrecord TmpFileSet [dirs files]
ITmpFileSet
(user-dirs [this] (temp-dirs-by dirs :user))
(input-dirs [this] (temp-dirs-by dirs :input))
(output-dirs [this] (temp-dirs-by dirs :output))
(user-files [this] (temp-files-for (user-dirs this)))
(input-files [this] (temp-files-for (input-dirs this)))
(output-files [this] (temp-files-for (output-dirs this)))
(add-asset! [this dir] (add-dir! this :asset dir))
(add-source! [this dir] (add-dir! this :source dir))
(add-resource! [this dir] (add-dir! this :resource dir)))
(comment
(def t1 (tmp-dir (io/file "foop1") :source))
(def t2 (tmp-dir (io/file "foop2") :resource))
(def tf (map->TmpFileSet {:dirs #{t1 t2} :files {}}))
(input-dirs tf)
(output-dirs tf)
(def tf (add-source! tf (io/file "foop3")))
(def tf (add-resource! tf (io/file "foop3")))
(file-seq (io/file "foop3/"))
(identity tf)
(user-files tf)
(input-files tf)
(output-files tf)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment