         (for-files [midfix-dir prefix-dir]
           (for-files [blob midfix-dir]
             blob))))))
+
+
+(defmacro ^:private when-blob-file
+  "This is an unhygenic macro which binds the blob file to 'file' and executes
+  the body only if it exists."
+  [store id & body]
+  `(let [~(with-meta 'file {:tag 'java.io.File})
+         (id->file (:root ~store) ~id)]
+     (when (.exists ~'file)
+       ~@body)))
 
 
 

    [clojure.string :as string]
    [vault.blob.core :as blob :refer [BlobStore]])
  (:import
    (java.io
      File)))


;; HELPER FUNCTIONS

(defn- hashid->file
  ^File
  [root id]
  (let [id (blob/hash-id id)
        {:keys [algorithm digest]} id]
    (io/file root
             (name algorithm)
             (subs digest 0 3)
             (subs digest 3 6)
             (subs digest 6))))


(defn- file->hashid
  [root file]
  (let [root (str root)
        file (str file)]

(extend-protocol BlobStore
  FileBlobStore

  (enumerate [this opts]
    (->> (enumerate-files (:root this))
         (map (partial file->id (:root this)))
         (blob/select-ids opts)))


  (stat [this id]
    (when-blob-file this id
      {:size (.length file)
       :stored-at (Date. (.lastModified file))
       :location (.toURI file)}))


  (open [this id]
    (when-blob-file this id
      (io/input-stream file)))


  (store! [this blob]
    (let [{:keys [id content]} blob
          file (id->file (:root this) id)]
      (when-not (.exists file)
        (io/make-parents file)
        ; For some reason, io/copy is much faster than byte-streams/transfer here.
