Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file tree_intf.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335(*
* Copyright (c) 2013-2017 Thomas Gazagnaire <thomas@gazagnaire.org>
* Copyright (c) 2017 Grégoire Henry <gregoire.henry@ocamlpro.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*)open!ImportmoduletypeS=sigtypekeytypesteptypemetadatatypecontentstypenodetypehash(** [Tree] provides immutable, in-memory partial mirror of the store, with
lazy reads and delayed writes.
Trees are like staging area in Git: they are immutable temporary
non-persistent areas (they disappear if the host crash), held in memory
for efficiency, where reads are done lazily and writes are done only when
needed on commit: if you modify a key twice, only the last change will be
written to the store when you commit. *)typet(** The type of trees. *)(** {1 Constructors} *)valempty:t(** [empty] is the empty tree. The empty tree does not have associated backend
configuration values, as they can perform in-memory operation,
independently of any given backend. *)valof_contents:?metadata:metadata->contents->t(** [of_contents c] is the subtree built from the contents [c]. *)valof_node:node->t(** [of_node n] is the subtree built from the node [n]. *)typeelt=[`Nodeofnode|`Contentsofcontents*metadata](** The type for tree elements. *)valv:elt->t(** General-purpose constructor for trees. *)valkind:t->key->[`Contents|`Node]optionLwt.t(** [kind t k] is the type of [s] in [t]. It could either be a tree node or
some file contents. It is [None] if [k] is not present in [t]. *)valis_empty:t->bool(** [is_empty t] is true iff [t] is {!empty} (i.e. a tree node with no
children). Trees with {!kind} = [`Contents] are never considered empty. *)(** {1 Diffs} *)valdiff:t->t->(key*(contents*metadata)Diff.t)listLwt.t(** [diff x y] is the difference of contents between [x] and [y]. *)(** {1 Manipulating Contents} *)type'aor_error=('a,[`Dangling_hashofhash])result(** Operations on lazy nodes can fail if the underlying store does not contain
the expected hash. *)(** Operations on lazy tree contents. *)moduleContents:sigtypet(** The type of lazy tree contents. *)valhash:t->hash(** [hash t] is the hash of the {!contents} value returned when [t] is
{!force}d successfully. *)valforce:t->contentsor_errorLwt.t(** [force t] forces evaluation of the lazy content value [t], or returns an
error if no such value exists in the underlying repository. *)valforce_exn:t->contentsLwt.t(** Equivalent to {!force}, but raises an exception if the lazy content
value is not present in the underlying repository. *)valclear:t->unit(** [clear t] clears [t]'s cache. *)endvalmem:t->key->boolLwt.t(** [mem t k] is true iff [k] is associated to some contents in [t]. *)valfind_all:t->key->(contents*metadata)optionLwt.t(** [find_all t k] is [Some (b, m)] if [k] is associated to the contents [b]
and metadata [m] in [t] and [None] if [k] is not present in [t]. *)vallength:node->intLwt.t(** [find n] is the number of entries in [n]. *)valfind:t->key->contentsoptionLwt.t(** [find] is similar to {!find_all} but it discards metadata. *)valget_all:t->key->(contents*metadata)Lwt.t(** Same as {!find_all} but raise [Invalid_arg] if [k] is not present in [t]. *)vallist:t->?offset:int->?length:int->key->(step*t)listLwt.t(** [list t key] is the list of files and sub-nodes stored under [k] in [t].
The result order is not specified but is stable.
[offset] and [length] are used for pagination. *)valget:t->key->contentsLwt.t(** Same as {!get_all} but ignore the metadata. *)valadd:t->key->?metadata:metadata->contents->tLwt.t(** [add t k c] is the tree where the key [k] is bound to the contents [c] but
is similar to [t] for other bindings. *)valupdate:t->key->?metadata:metadata->(contentsoption->contentsoption)->tLwt.t(** [update t k f] is the tree [t'] that is the same as [t] for all keys
except [k], and whose binding for [k] is determined by [f (find t k)].
If [k] refers to an internal node of [t], [f] is called with [None] to
determine the value with which to replace it. *)valremove:t->key->tLwt.t(** [remove t k] is the tree where [k] bindings has been removed but is
similar to [t] for other bindings. *)(** {1 Manipulating Subtrees} *)valmem_tree:t->key->boolLwt.t(** [mem_tree t k] is false iff [find_tree k = None]. *)valfind_tree:t->key->toptionLwt.t(** [find_tree t k] is [Some v] if [k] is associated to [v] in [t]. It is
[None] if [k] is not present in [t]. *)valget_tree:t->key->tLwt.t(** [get_tree t k] is [v] if [k] is associated to [v] in [t]. Raise
[Invalid_arg] if [k] is not present in [t].*)valadd_tree:t->key->t->tLwt.t(** [add_tree t k v] is the tree where the key [k] is bound to the non-empty
tree [v] but is similar to [t] for other bindings.
If [v] is empty, this is equivalent to [remove t k]. *)valupdate_tree:t->key->(toption->toption)->tLwt.t(** [update_tree t k f] is the tree [t'] that is the same as [t] for all
subtrees except under [k], and whose subtree at [k] is determined by
[f (find_tree t k)].
[f] returning either [None] or [Some empty] causes the subtree at [k] to
be unbound (i.e. it is equivalent to [remove t k]). *)valmerge:tMerge.t(** [merge] is the 3-way merge function for trees. *)(** {1 Folds} *)valdestruct:t->[`Nodeofnode|`ContentsofContents.t*metadata](** General-purpose destructor for trees. *)typemarks(** The type for fold marks. *)valempty_marks:unit->marks(** [empty_marks ()] is an empty collection of marks. *)type'aforce=[`True|`Falseofkey->'a->'aLwt.t|`And_clear](** The type for {!fold}'s [force] parameter. [`True] forces the fold to read
the objects of the lazy nodes and contents. [`False f] is applying [f] on
every lazy node and content value instead. [`And_clear] is like [`True]
but also eagerly empties the Tree caches when traversing sub-nodes. *)typeuniq=[`False|`True|`Marksofmarks](** The type for {!fold}'s [uniq] parameters. [`False] folds over all the
nodes. [`True] does not recurse on nodes already seen. [`Marks m] uses the
collection of marks [m] to store the cache of keys: the fold will modify
[m]. This can be used for incremental folds. *)type'anode_fn=key->steplist->'a->'aLwt.t(** The type for {!fold}'s [pre] and [post] parameters. *)typedepth=[`Eqofint|`Leofint|`Ltofint|`Geofint|`Gtofint][@@derivingirmin](** The type for fold depths.
- [Eq d] folds over nodes and contents of depth exactly [d].
- [Lt d] folds over nodes and contents of depth strictly less than [d].
- [Gt d] folds over nodes and contents of depth strictly more than [d].
[Le d] is [Eq d] and [Lt d]. [Ge d] is [Eq d] and [Gt d]. *)valfold:?force:'aforce->?uniq:uniq->?pre:'anode_fn->?post:'anode_fn->?depth:depth->?contents:(key->contents->'a->'aLwt.t)->?node:(key->node->'a->'aLwt.t)->t->'a->'aLwt.t(** [fold f t acc] folds [f] over [t]'s leafs.
For every node [n], ui [n] is a leaf node, call [f path n]. Otherwise:
- Call [pre path n]. By default [pre] is the identity;
- Recursively call [fold] on each children, in lexicographic order;
- Call [post path n]; By default [post] is the identity.
See {!force} for details about the [force] parameters. By default it is
[`And_clear].
See {!uniq} for details about the [uniq] parameters. By default it is
[`False].
The fold depth is controlled by the [depth] parameter. *)(** {1 Stats} *)typestats={nodes:int;(** Number of node. *)leafs:int;(** Number of leafs. *)skips:int;(** Number of lazy nodes. *)depth:int;(** Maximal depth. *)width:int;(** Maximal width. *)}[@@derivingirmin](** The type for tree stats. *)valstats:?force:bool->t->statsLwt.t(** [stats ~force t] are [t]'s statistics. If [force] is true, this will force
the reading of lazy nodes. By default it is [false]. *)(** {1 Concrete Trees} *)typeconcrete=[`Treeof(step*concrete)list|`Contentsofcontents*metadata](** The type for concrete trees. *)valconcrete_t:concreteType.t(** The value-type for {!concrete}. *)valof_concrete:concrete->t(** [of_concrete c] is the subtree equivalent of the concrete tree [c].
@raise Invalid_argument if [c] contains duplicate bindings for a given
path. *)valto_concrete:t->concreteLwt.t(** [to_concrete t] is the concrete tree equivalent of the subtree [t]. *)(** {1 Caches} *)valclear:?depth:int->t->unit(** [clear ?depth t] clears all caches in the tree [t] for subtrees with a
depth higher than [depth]. If [depth] is not set, all of the subtrees are
cleared. *)(** {1 Performance counters} *)typecounters={mutablecontents_hash:int;mutablecontents_find:int;mutablecontents_add:int;mutablenode_hash:int;mutablenode_mem:int;mutablenode_add:int;mutablenode_find:int;mutablenode_val_v:int;mutablenode_val_find:int;mutablenode_val_list:int;}valcounters:unit->countersvaldump_counters:unitFmt.tvalreset_counters:unit->unitvalinspect:t->[`Contents|`Nodeof[`Map|`Hash|`Value]]endmoduletypeTree=sigmoduletypeS=sigincludeS(** @inline *)endmoduleMake(P:Private.S):sigincludeSwithtypekey=P.Node.Path.tandtypestep=P.Node.Path.stepandtypemetadata=P.Node.Metadata.tandtypecontents=P.Contents.valueandtypehash=P.Hash.ttypekinded_hash:=[`Contentsofhash*metadata|`Nodeofhash]valimport:P.Repo.t->kinded_hash->toptionLwt.tvalimport_no_check:P.Repo.t->kinded_hash->tvalexport:?clear:bool->P.Repo.t->[>write]P.Contents.t->[>read_write]P.Node.t->node->P.Node.keyLwt.tvaldump:tFmt.tvalequal:t->t->boolvalnode_t:nodeType.tvaltree_t:tType.tvalhash:t->kinded_hashvalof_private_node:P.Repo.t->P.Node.value->nodevalto_private_node:node->P.Node.valueor_errorLwt.tendend