package datakit

  1. Overview
  2. Docs

Make an DataKit store from a normal Irmin backend.

Parameters

module M : Irmin.S_MAKER

Signature

Irmin stores

Irmin stores are tree-like read-write stores with extended capabilities. They allow an application (or a collection of applications) to work with multiple local states, which can be forked and merged programmatically, without having to rely on a global state. In a way very similar to version control systems, Irmin local states are called branches.

There are two kinds of store in Irmin: the ones based on persistent named branches and the ones based temporary detached heads. These exist relative to a local, larger (and shared) store, and have some (shared) contents. This is exactly the same as usual version control systems, that the informed user can see as an implicit purely functional data-structure.

type repo

The type for Irmin repositories.

type t

The type for Irmin stores.

type step = step

The type for key steps.

type key = path

The type for store keys. A key is a sequence of steps.

type metadata = perm

The type for store metadata.

type contents = blob

The type for store contents.

type node

The type for store nodes.

type tree = [
  1. | `Node of node
  2. | `Contents of contents * metadata
]

The type for store trees.

type commit

Type for commit identifiers. Similar to Git's commit SHA1s.

type branch = string

Type for persistent branch names. Branches usually share a common global namespace and it's the user's responsibility to avoid name clashes.

type slice

Type for store slices.

type lca_error = [
  1. | `Max_depth_reached
  2. | `Too_many_lcas
]

The type for errors associated with functions computing least common ancestors

type ff_error = [
  1. | `No_change
  2. | `Rejected
  3. | lca_error
]

The type for errors for fast_forward.

module Repo : sig ... end

Repositories.

val empty : repo -> t Lwt.t

empty repo is a temporary, empty store. Becomes a normal temporary store after the first update.

val master : repo -> t Lwt.t

master repo is a persistent store based on r's master branch. This operation is cheap, can be repeated multiple times.

val of_branch : repo -> branch -> t Lwt.t

of_branch r name is a persistent store based on the branch name. Similar to master, but use name instead Branch.S.master.

val of_commit : commit -> t Lwt.t

of_commit c is a temporary store, based on the commit c.

Temporary stores do not have stable names: instead they can be addressed using the hash of the current commit. Temporary stores are similar to Git's detached heads. In a temporary store, all the operations are performed relative to the current head and update operations can modify the current head: the current stores's head will automatically become the new head obtained after performing the update.

val repo : t -> repo

repo t is the repository containing t.

val tree : t -> tree Lwt.t

tree t is t's current tree. Contents is not allowed at the root of the tree.

module Status : sig ... end

Status provides base functions for store statuses.

val status : t -> Status.t

status t is t's status. It can either be a branch, a commit or empty.

module Head : sig ... end

Managing the store's heads.

module Commit : sig ... end

Commit defines immutable objects to describe store updates.

Managing store's trees.

module Tree : sig ... end

Tree provides immutable, in-memory partial mirror of the store, with lazy reads and delayed writes.

module Contents : sig ... end

Contents provides base functions for the store's contents.

Reads

val kind : t -> key -> [ `Contents | `Node ] option Lwt.t

kind is Tree.kind applied to t's root tree.

val list : t -> key -> (step * [ `Contents | `Node ]) list Lwt.t

list t is Tree.list applied to t's root tree.

val mem : t -> key -> bool Lwt.t

mem t is Tree.mem applied to t's root tree.

val mem_tree : t -> key -> bool Lwt.t

mem_tree t is Tree.mem_tree applied to t's root tree.

val find_all : t -> key -> (contents * metadata) option Lwt.t

find_all t is Tree.find_all applied to t's root tree.

val find : t -> key -> contents option Lwt.t

find t is Tree.find applied to t's root tree.

val get_all : t -> key -> (contents * metadata) Lwt.t

get_all t is Tree.get_all applied on t's root tree.

val get : t -> key -> contents Lwt.t

get t is Tree.get applied to t's root tree.

val find_tree : t -> key -> tree option Lwt.t

find_tree t is Tree.find_tree applied to t's root tree.

val get_tree : t -> key -> tree Lwt.t

get_tree t k is Tree.get_tree applied to t's root tree.

Transactions

type 'a transaction = ?allow_empty:bool -> ?strategy:[ `Set | `Test_and_set | `Merge ] -> ?max_depth:int -> ?n:int -> info:Irmin.Info.f -> 'a -> unit Lwt.t

The type for transactions.

val with_tree : t -> key -> (tree option -> tree option Lwt.t) transaction

with_tree t k ~info f replaces atomically the subtree v under k in the store t by the contents of the tree f v, using the commit info info ().

If v = f v and allow_empty is unset (default) then, the operation is a no-op.

If v != f v and no other changes happen concurrently, f v becomes the new subtree under k. If other changes happen concurrently to that operations, the semantics depend on the value of strategy:

  • if strategy = `Set, the last write wins.
  • if strategy = `Test_and_set (default), the transaction is restarted.
  • if strategy = `Merge, concurrent changes are merged with f v. If the merge has a conflict, the transaction is restarted.

Note: Irmin transactions provides snapshot isolation guarantees: reads and writes are isolated in every transaction, but only write conflicts are visible on commit.

val set : t -> key -> ?metadata:metadata -> contents transaction

set t k ~info v is with_tree t k ~info (fun tree -> Tree.add tree [] v).

val set_tree : t -> key -> tree transaction

set_tree t k ~info v is with_tree t k ~info (fun tree -> Tree.add_tree tree [] v).

val remove : t -> key transaction

remove t i k is with_tree t i k (fun tree -> Tree.remove tree []).

Clones

val clone : src:t -> dst:branch -> t Lwt.t

clone ~src ~dst makes dst points to Head.get src. dst is created if needed. Remove the current contents en dst if src is empty.

Watches

type watch

The type for store watches.

val watch : t -> ?init:commit -> (commit Irmin.diff -> unit Lwt.t) -> watch Lwt.t

watch t f calls f every time the contents of t's head is updated.

Note: even if f might skip some head updates, it will never be called concurrently: all consecutive calls to f are done in sequence, so we ensure that the previous one ended before calling the next one.

val watch_key : t -> key -> ?init:commit -> ((commit * tree) Irmin.diff -> unit Lwt.t) -> watch Lwt.t

watch_key t key f calls f every time the key's value is added, removed or updated. If the current branch is deleted, no signal is sent to the watcher.

val unwatch : watch -> unit Lwt.t

unwatch w disable w. Return once the w is fully disabled.

Merges and Common Ancestors.

type 'a merge = info:Irmin.Info.f -> ?max_depth:int -> ?n:int -> 'a -> (unit, Irmin.Merge.conflict) Result.result Lwt.t

The type for merge functions.

val merge : into:t -> t merge

merge ~into i t merges t's current branch into x's current branch using the info i. After that operation, the two stores are still independent. Similar to git merge <branch>.

val merge_with_branch : t -> branch merge

Same as merge but with a branch ID.

val merge_with_commit : t -> commit merge

Same as merge but with a commit ID.

val lcas : ?max_depth:int -> ?n:int -> t -> t -> (commit list, lca_error) Result.result Lwt.t

lca ?max_depth ?n msg t1 t2 returns the collection of least common ancestors between the heads of t1 and t2 branches.

  • max_depth is the maximum depth of the exploration (default is max_int). Return Error `Max_depth_reached if this depth is exceeded.
  • n is the maximum expected number of lcas. Stop the exploration as soon as n lcas are found. Return Error `Too_many_lcas if more lcas are found.
val lcas_with_branch : t -> ?max_depth:int -> ?n:int -> branch -> (commit list, lca_error) Result.result Lwt.t

Same as lcas but takes a branch ID as argument.

val lcas_with_commit : t -> ?max_depth:int -> ?n:int -> commit -> (commit list, lca_error) Result.result Lwt.t

Same as lcas but takes a commit ID as argument.

History

module History : Graph.Sig.P with type V.t = commit

An history is a DAG of heads.

val history : ?depth:int -> ?min:commit list -> ?max:commit list -> t -> History.t Lwt.t

history ?depth ?min ?max t is a view of the history of the store t, of depth at most depth, starting from the max (or from the t's head if the list of heads is empty) and stopping at min if specified.

module Branch : sig ... end

Manipulate branches.

module Key : Irmin.Path.S with type t = key and type step = step

Key provides base functions for the stores's paths.

module Metadata : Irmin.Metadata.S with type t = metadata

Metadata provides base functions for node metadata.

Value Types

val step_t : step Irmin.Type.t

step_t is the value type for step.

val key_t : key Irmin.Type.t

key_t is the value type for key.

val metadata_t : metadata Irmin.Type.t

metadata_t is the value type for metadata.

val contents_t : contents Irmin.Type.t

contents_t is the value type for contents.

val node_t : node Irmin.Type.t

node_t is the value type for node.

val tree_t : tree Irmin.Type.t

tree_t is the value type for tree.

val commit_t : repo -> commit Irmin.Type.t

commit_t r is the value type for commit.

val branch_t : branch Irmin.Type.t

branch_t is the value type for branch.

val slice_t : slice Irmin.Type.t

slice_t is the value type for slice.

val kind_t : [ `Node | `Contents ] Irmin.Type.t

kind_t is the value type for values returned by kind.

val lca_error_t : lca_error Irmin.Type.t

lca_error_t is the value type for lca_error.

val ff_error_t : ff_error Irmin.Type.t

ff_error_t is the value type for ff_error.

module Private : sig ... end

Private functions, which might be used by the backends.

OCaml

Innovation. Community. Security.