Initial checkin
This commit is contained in:
commit
9d6ed7453d
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
:paths ["src"]
|
||||
|
||||
:deps {
|
||||
org.clojure/clojure { :mvn/version "1.11.1" }
|
||||
org.clojure/core.async { :mvn/version "1.5.648" }
|
||||
}
|
||||
:aliases {
|
||||
:test {
|
||||
:extra-paths ["test"]
|
||||
:extra-deps {
|
||||
io.github.cognitect-labs/test-runner
|
||||
{
|
||||
:git/url "https://github.com/cognitect-labs/test-runner.git"
|
||||
:sha "dfb30dd6605cb6c0efc275e1df1736f6e90d4d73"
|
||||
}
|
||||
}
|
||||
:main-opts ["-m" "cognitect.test-runner"]
|
||||
:exec-fn cognitect.test-runner.api/test
|
||||
}
|
||||
|
||||
:lint {
|
||||
:replace-deps { clj-kondo/clj-kondo {:mvn/version "2022.04.25"} }
|
||||
:main-opts ["-m" "clj-kondo.main" "--lint" "src"]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
(ns firmament.connection
|
||||
(:require [clojure.edn :as edn])
|
||||
(:import java.security.MessageDigest))
|
||||
|
||||
(defprotocol IFirmConnection
|
||||
(read! [self id])
|
||||
(write! [self data]))
|
||||
|
||||
(defn- sha256 [string]
|
||||
(let [digest (.digest (MessageDigest/getInstance "SHA-256")
|
||||
(.getBytes string "UTF-8"))]
|
||||
(apply str (map (partial format "%02x") digest))))
|
||||
|
||||
(defn firmament-cache []
|
||||
(let [store (atom {})]
|
||||
(reify IFirmConnection
|
||||
(read! [_ id]
|
||||
(some-> (get @store id)
|
||||
(edn/read-string)))
|
||||
(write! [_ data]
|
||||
(let [data-str (-> data prn-str)
|
||||
id (sha256 data-str)]
|
||||
(swap! store assoc id data-str)
|
||||
id)))))
|
|
@ -0,0 +1,26 @@
|
|||
(ns firmament.core
|
||||
(:require [clojure.string :as str]))
|
||||
|
||||
;; Namespaces and code files
|
||||
|
||||
;; Dependencies specify namespaces, and the same rules as clojure apply
|
||||
|
||||
|
||||
(defprotocol IFirmFilesystem
|
||||
(read [self filename])
|
||||
(write [self filename content])
|
||||
(entries [self dirname]))
|
||||
|
||||
(defn make-filesystem
|
||||
([conn] (make-filesystem [conn nil]))
|
||||
([conn original-root]
|
||||
(let [root (atom original-root)]
|
||||
(reify IFirmFilesystem
|
||||
(read [_ path]
|
||||
(read-file conn @root path))
|
||||
(write [_ path content]
|
||||
(swap! root
|
||||
(fn [old-root]
|
||||
(write-path conn old-root path content))))
|
||||
(entries [_ dirname]
|
||||
(list-entries conn @root dirname))))))
|
|
@ -0,0 +1,36 @@
|
|||
(ns firmament.directory
|
||||
(:require [firmament.directory :as dir]
|
||||
[firmament.type :as t]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
(s/def ::entries (s/map-of keyword? ::t/firmament-id))
|
||||
|
||||
(defn create [& entries]
|
||||
{::t/type ::t/directory
|
||||
::entries (apply hash-map entries)})
|
||||
|
||||
(defn entry-id [dir entry]
|
||||
(get-in dir [::entries entry]))
|
||||
|
||||
#_(defn- load-entry! [conn dir entry]
|
||||
(conn/read! conn (get-entry-id dir entry)))
|
||||
|
||||
#_(defn- read-or-create! [conn id]
|
||||
(if-let [dir (conn/read! conn id)]
|
||||
dir
|
||||
(create)))
|
||||
|
||||
#_(defn load! [conn dir entry]
|
||||
(dir/read-or-create! conn (get-entry-id dir entry)))
|
||||
|
||||
#_(defn add-entry! [conn dir entry data]
|
||||
(assoc-in dir [::entries entry] (conn/write conn data)))
|
||||
|
||||
(defn entries [dir]
|
||||
(::entries dir))
|
||||
|
||||
(defn add-entry [dir entry id]
|
||||
(assoc-in dir [::entries entry] id))
|
||||
|
||||
(defn directory? [o]
|
||||
(and (map? o) (= ::t/directory (::t/type o))))
|
|
@ -0,0 +1,21 @@
|
|||
(ns firmament.filesystem
|
||||
(:require [firmament.path :as path]))
|
||||
|
||||
(defprotocol IFirmFilesystem
|
||||
(read! [self filename])
|
||||
(write! [self filename content])
|
||||
(entries! [self dirname]))
|
||||
|
||||
(defn make-filesystem
|
||||
([conn] (make-filesystem conn nil))
|
||||
([conn original-root]
|
||||
(let [root (atom original-root)]
|
||||
(reify IFirmFilesystem
|
||||
(read! [_ path]
|
||||
(path/read-file! conn @root path))
|
||||
(write! [_ path content]
|
||||
(swap! root
|
||||
(fn [old-root]
|
||||
(path/write! conn old-root path content))))
|
||||
(entries! [_ dirname]
|
||||
(path/list-entries! conn @root dirname))))))
|
|
@ -0,0 +1,8 @@
|
|||
(ns firmament.object
|
||||
(:require [firmament.type :as t]))
|
||||
|
||||
(defn create [data]
|
||||
{::t/type ::t/object ::t/data data})
|
||||
|
||||
(defn data [obj]
|
||||
(::t/data obj))
|
|
@ -0,0 +1,49 @@
|
|||
(ns firmament.path
|
||||
(:require [clojure.string :as str]
|
||||
[firmament.directory :as dir]
|
||||
[firmament.object :as object]
|
||||
[firmament.connection :as conn]))
|
||||
|
||||
(defn- path-elements [path]
|
||||
(str/split path #"/"))
|
||||
|
||||
(defn- read! [conn root path]
|
||||
(loop [curr (conn/read! conn root)
|
||||
remaining (path-elements path)]
|
||||
(when (nil? curr)
|
||||
(throw (ex-info (str "path does not exist: " path)
|
||||
{:root root})))
|
||||
(if (not (seq remaining))
|
||||
curr
|
||||
(recur (conn/read! conn (dir/entry-id curr (first remaining)))
|
||||
(rest remaining)))))
|
||||
|
||||
(defn read-file! [conn root path]
|
||||
(some-> (read! conn root path) (object/data)))
|
||||
|
||||
(defn list-entries! [conn root path]
|
||||
(some-> (read! conn root path) (dir/entries) (keys)))
|
||||
|
||||
(defn save-entry! [conn dir entry data]
|
||||
(dir/add-entry dir entry (conn/write! conn data)))
|
||||
|
||||
(defn load-dir-entry! [conn base entry]
|
||||
(if-let [dir (conn/read! conn (dir/entry-id base entry))]
|
||||
dir
|
||||
(dir/create)))
|
||||
|
||||
(defn- write-internal [conn curr [el & els] obj]
|
||||
(if (seq els)
|
||||
(save-entry! conn curr el
|
||||
(write-internal conn
|
||||
(load-dir-entry! conn curr el)
|
||||
els
|
||||
obj))
|
||||
(save-entry! conn curr el obj)))
|
||||
|
||||
(defn write! [conn root path data]
|
||||
(conn/write! conn
|
||||
(write-internal conn
|
||||
(conn/read! conn root)
|
||||
(path-elements path)
|
||||
(object/create data))))
|
|
@ -0,0 +1,12 @@
|
|||
(ns firmament.type
|
||||
(:require [clojure.spec.alpha :as s]))
|
||||
|
||||
(def firmament-id? string?)
|
||||
|
||||
(s/def ::firmament-id firmament-id?)
|
||||
|
||||
(def firmament-data? string?)
|
||||
|
||||
(s/def ::type #{::directory ::object})
|
||||
|
||||
(s/def ::data firmament-data?)
|
Loading…
Reference in New Issue