; lib/git/object.sx — sx-git Phase 1: blob/tree/commit/tag as content-addressed ; TYPED objects over the persist kv store. Identity = host digest of the ; canonical serialization (artdag/canon: sorted dict keys, escaped strings) — ; native CIDs, NOT git wire bytes. Objects are plain dicts: typed, extensible; ; unknown fields round-trip and participate in the CID. ; Requires: lib/persist/backend.sx, lib/persist/kv.sx, lib/artdag/dag.sx. ; ---- canonical form + content id ---- (define git/canon (fn (obj) (artdag/canon obj))) (define git/cid (fn (obj) (str "sx1:" (crypto-sha256 (artdag/canon obj))))) ; ---- repo handle: a persist backend + key prefix (many repos per db) ---- (define git/repo-named (fn (db name) {:prefix name :db db})) (define git/repo (fn (db) (git/repo-named db "git"))) (define git/repo-db (fn (repo) (get repo :db))) (define git/obj-key (fn (repo cid) (str (get repo :prefix) "/obj/" cid))) ; ---- constructors ---- (define git/blob (fn (data) {:data data :type "blob"})) ; entries: dict of name -> entry, entry = {:kind "blob"|"tree" :cid cid ...} (define git/tree (fn (entries) {:type "tree" :entries entries})) (define git/tree-entry (fn (kind cid) {:kind kind :cid cid})) ; meta: open dict (:author :message :time ... anything); protected keys win (define git/commit (fn (tree parents meta) (merge meta {:type "commit" :tree tree :parents parents}))) (define git/tag (fn (target name meta) (merge meta {:name name :type "tag" :target target}))) ; ---- predicates / accessors ---- (define git/object-type (fn (obj) (get obj :type))) (define git/blob? (fn (obj) (and (dict? obj) (equal? (get obj :type) "blob")))) (define git/tree? (fn (obj) (and (dict? obj) (equal? (get obj :type) "tree")))) (define git/commit? (fn (obj) (and (dict? obj) (equal? (get obj :type) "commit")))) (define git/tag? (fn (obj) (and (dict? obj) (equal? (get obj :type) "tag")))) (define git/blob-data (fn (obj) (get obj :data))) (define git/tree-entries (fn (obj) (get obj :entries))) (define git/tree-entry-for (fn (obj name) (get (get obj :entries) name))) (define git/tree-names (fn (obj) (artdag/sort-strings (keys (get obj :entries))))) (define git/entry-cid (fn (entry) (get entry :cid))) (define git/entry-kind (fn (entry) (get entry :kind))) (define git/commit-tree (fn (obj) (get obj :tree))) (define git/commit-parents (fn (obj) (get obj :parents))) (define git/commit-author (fn (obj) (get obj :author))) (define git/commit-message (fn (obj) (get obj :message))) (define git/tag-target (fn (obj) (get obj :target))) (define git/tag-name (fn (obj) (get obj :name))) ; ---- object store: write/read/has, keyed by cid ---- (define git/write (fn (repo obj) (let ((cid (git/cid obj))) (begin (persist/kv-put (get repo :db) (git/obj-key repo cid) obj) cid)))) (define git/read (fn (repo cid) (persist/kv-get (get repo :db) (git/obj-key repo cid)))) (define git/has? (fn (repo cid) (persist/kv-has? (get repo :db) (git/obj-key repo cid)))) ; convenience: write a blob straight from data (define git/write-blob (fn (repo data) (git/write repo (git/blob data))))