Persistent store with Git semantics: lazy reads, delayed writes, content-addressing
at main 120 lines 3.6 kB view raw
1(** Lazy trees with delayed writes. 2 3 Trees are like Git's staging area: immutable, temporary, non-persistent 4 areas held in memory. Reads are done lazily and writes are accumulated until 5 commit - if you modify a key twice, only the last change is written. *) 6 7(** {1 Tree Functor} *) 8 9module Make (F : Codec.S) : sig 10 type t 11 (** Immutable in-memory tree with lazy reads and delayed writes. *) 12 13 type hash = F.hash 14 15 (** {2 Path Type} *) 16 17 type path = string list 18 (** A path is a list of path segments. *) 19 20 (** {2 Concrete Trees} *) 21 22 type concrete = [ `Contents of string | `Tree of (string * concrete) list ] 23 (** Fully materialized tree for import/export. *) 24 25 (** {2 Construction} *) 26 27 val empty : unit -> t 28 (** [empty ()] creates an empty tree. *) 29 30 val of_hash : backend:hash Backend.t -> hash -> t 31 (** [of_hash ~backend h] creates a tree backed by the store. Nothing is loaded 32 until accessed (lazy reads). *) 33 34 val of_concrete : concrete -> t 35 (** [of_concrete c] creates a tree from a fully materialized tree. *) 36 37 val shallow : hash -> t 38 (** [shallow h] creates a tree with only a hash reference. Accessing contents 39 raises an error. *) 40 41 val pruned : hash -> t 42 (** [pruned h] creates a pruned tree that raises on dereference. Used for GC 43 and export operations. *) 44 45 (** {2 Reads (Lazy)} *) 46 47 val find : t -> path -> string option 48 (** [find t path] looks up contents at [path]. Loads nodes lazily as needed. 49 *) 50 51 val find_tree : t -> path -> t option 52 (** [find_tree t path] looks up a subtree at [path]. *) 53 54 val list : t -> path -> (string * [ `Node | `Contents ]) list 55 (** [list t path] lists entries at [path]. *) 56 57 val mem : t -> path -> bool 58 (** [mem t path] checks if [path] exists. *) 59 60 val mem_tree : t -> path -> bool 61 (** [mem_tree t path] checks if a subtree exists at [path]. *) 62 63 (** {2 Writes (Delayed)} *) 64 65 val add : t -> path -> string -> t 66 (** [add t path contents] adds contents at [path]. The write is accumulated, 67 not performed immediately. *) 68 69 val add_tree : t -> path -> t -> t 70 (** [add_tree t path subtree] adds a subtree at [path]. *) 71 72 val remove : t -> path -> t 73 (** [remove t path] removes the entry at [path]. *) 74 75 (** {2 Materialization} *) 76 77 val to_concrete : t -> concrete 78 (** [to_concrete t] fully materializes the tree. Forces all lazy nodes to be 79 loaded. *) 80 81 val hash : t -> backend:hash Backend.t -> hash 82 (** [hash t ~backend] computes the tree hash. Writes all accumulated changes 83 to the backend. *) 84 85 (** {2 Force Control} *) 86 87 type 'a force = [ `True | `False of hash -> 'a | `Shallow of hash -> 'a ] 88 (** Control how lazy nodes are handled during traversal: 89 - [`True]: force loading of all nodes 90 - [`False f]: call [f] on unloaded hashes instead 91 - [`Shallow f]: like [`False] but for shallow trees *) 92 93 val fold : 94 ?force:'a force -> 95 t -> 96 'a -> 97 (path -> [ `Contents of string | `Tree ] -> 'a -> 'a) -> 98 'a 99 (** [fold ~force t init f] traverses the tree. The [force] parameter controls 100 lazy loading behavior. *) 101 102 (** {2 Cache Management} *) 103 104 val clear : ?depth:int -> t -> unit 105 (** [clear ?depth t] purges cached data. If [depth] is given, only clears 106 nodes at that depth or deeper. *) 107 108 (** {2 Comparison} *) 109 110 val equal : t -> t -> bool 111 (** [equal t1 t2] compares trees structurally. *) 112end 113 114(** {1 Pre-instantiated Trees} *) 115 116module Git : module type of Make (Codec.Git) 117(** Git-format trees with SHA-1 hashes. *) 118 119module Mst : module type of Make (Codec.Mst) 120(** MST-format trees with SHA-256 hashes. *)