open Import

(** A cached file-system operation on a [Path.t] whose result type is ['a]. For
    example, an operation to check if a path exists returns ['a = bool].

    Currently we do not expose a way to construct such cached operations; see
    the [Untracked] module for a few predefined ones. *)
type 'a t

(** If the cache contains the result of applying an operation to a path, return
    it. Otherwise, perform the operation, store the result in the cache, and
    then return it. *)
val read : 'a t -> Path.t -> 'a

(** Evict an entry from the cache. *)
val evict : 'a t -> Path.t -> unit

(** Result of updating a cache entry. *)
module Update_result : sig
  type t =
    | Skipped  (** No need to update a given entry because it has no readers *)
    | Updated of { changed : bool }

  (** [Skipped] is the "empty" update. *)
  val empty : t

  val combine : t -> t -> t

  val to_dyn : t -> Dyn.t
end

(** Perform an operation and update the result stored in the cache. *)
val update : 'a t -> Path.t -> Update_result.t

* This module caches only a subset of fields of [ Unix.stats ] because other 
     fields are currently unused . 

     Note that we specifically do not want to cache [  ] and [ ctime ] because 
     these fields can change too often : for example , when a temporary file is 
     created in a watched directory .
    fields are currently unused.

    Note that we specifically do not want to cache [mtime] and [ctime] because
    these fields can change too often: for example, when a temporary file is
    created in a watched directory. *)
module Reduced_stats : sig
  type t =
    { st_dev : int  (** Device number *)
*  number
    ; st_kind : File_kind.t  (** Kind of the file *)
    }

  val of_unix_stats : Unix.stats -> t

  val equal : t -> t -> bool
end

module Dir_contents : sig
  type t

  (** The sorted list of file names with kinds. *)
  val to_list : t -> (string * File_kind.t) list

  val iter : t -> f:(string * File_kind.t -> unit) -> unit

  val equal : t -> t -> bool
end

* A few predefined cached operations . They are " untracked " in the sense that 
     the user is responsible for tracking the file system and manually calling 
     the [ update ] function to bring the stored results up to date . 

     See [ fs_memo.ml ] for tracked versions of these operations .
    the user is responsible for tracking the file system and manually calling
    the [update] function to bring the stored results up to date.

    See [fs_memo.ml] for tracked versions of these operations. *)
module Untracked : sig
  val path_stat : (Reduced_stats.t, Unix_error.Detailed.t) result t

  val file_digest : Cached_digest.Digest_result.t t

  val dir_contents : (Dir_contents.t, Unix_error.Detailed.t) result t
end

module Debug : sig
  (** The name of a cached operation. *)
  val name : 'a t -> string
end

* A cached file-system operation on a [Path.t] whose result type is ['a]. For
    example, an operation to check if a path exists returns ['a = bool].

    Currently we do not expose a way to construct such cached operations; see
    the [Untracked] module for a few predefined ones. 
* If the cache contains the result of applying an operation to a path, return
    it. Otherwise, perform the operation, store the result in the cache, and
    then return it. 
* Evict an entry from the cache. 
* Result of updating a cache entry. 
* No need to update a given entry because it has no readers 
* [Skipped] is the "empty" update. 
* Perform an operation and update the result stored in the cache. 
* Device number 
* Kind of the file 
* The sorted list of file names with kinds. 
* The name of a cached operation. 
open Import

type 'a t

val read : 'a t -> Path.t -> 'a

val evict : 'a t -> Path.t -> unit

module Update_result : sig
  type t =
    | Updated of { changed : bool }

  val empty : t

  val combine : t -> t -> t

  val to_dyn : t -> Dyn.t
end

val update : 'a t -> Path.t -> Update_result.t

* This module caches only a subset of fields of [ Unix.stats ] because other 
     fields are currently unused . 

     Note that we specifically do not want to cache [  ] and [ ctime ] because 
     these fields can change too often : for example , when a temporary file is 
     created in a watched directory .
    fields are currently unused.

    Note that we specifically do not want to cache [mtime] and [ctime] because
    these fields can change too often: for example, when a temporary file is
    created in a watched directory. *)
module Reduced_stats : sig
  type t =
*  number
    }

  val of_unix_stats : Unix.stats -> t

  val equal : t -> t -> bool
end

module Dir_contents : sig
  type t

  val to_list : t -> (string * File_kind.t) list

  val iter : t -> f:(string * File_kind.t -> unit) -> unit

  val equal : t -> t -> bool
end

* A few predefined cached operations . They are " untracked " in the sense that 
     the user is responsible for tracking the file system and manually calling 
     the [ update ] function to bring the stored results up to date . 

     See [ fs_memo.ml ] for tracked versions of these operations .
    the user is responsible for tracking the file system and manually calling
    the [update] function to bring the stored results up to date.

    See [fs_memo.ml] for tracked versions of these operations. *)
module Untracked : sig
  val path_stat : (Reduced_stats.t, Unix_error.Detailed.t) result t

  val file_digest : Cached_digest.Digest_result.t t

  val dir_contents : (Dir_contents.t, Unix_error.Detailed.t) result t
end

module Debug : sig
  val name : 'a t -> string
end
