package irmin-git

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file backend.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
(*
 * Copyright (c) 2013-2022 Thomas Gazagnaire <thomas@gazagnaire.org>
 *
 * 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 Import

module type G = sig
  include Git.S

  val v : ?dotgit:Fpath.t -> Fpath.t -> (t, error) result Lwt.t
end

module Make
    (G : G)
    (S : Git.Sync.S with type hash := G.hash and type store := G.t)
    (Schema : Schema.S
                with type Hash.t = G.hash
                 and type Node.t = G.Value.Tree.t
                 and type Commit.t = G.Value.Commit.t) =
struct
  module Hash = Irmin.Hash.Make (G.Hash)
  module Schema = Schema
  module Key = Irmin.Key.Of_hash (Hash)
  module Commit_key = Key
  module Node_key = Key

  module Contents = struct
    module S = Contents.Make (G) (Schema.Contents)
    include Irmin.Contents.Store (S) (S.Hash) (S.Val)
  end

  module Node = struct
    module S = Node.Store (G) (Schema.Path)

    include
      Irmin.Node.Store (Contents) (S) (S.Key) (S.Val) (Metadata) (Schema.Path)
  end

  module Node_portable = Irmin.Node.Portable.Of_node (Node.Val)

  module Commit = struct
    module S = Commit.Store (G)
    include Irmin.Commit.Store (Schema.Info) (Node) (S) (S.Hash) (S.Val)
  end

  module Commit_portable = Irmin.Commit.Portable.Of_commit (Commit.S.Val)

  module Branch = struct
    module Key = Schema.Branch
    module Val = Commit_key
    module S = Atomic_write.Make (Schema.Branch) (G)
    include Atomic_write.Check_closed (S)

    let v ?lock ~head ~bare t = S.v ?lock ~head ~bare t >|= v
  end

  module Slice = Irmin.Backend.Slice.Make (Contents) (Node) (Commit)

  module Repo = struct
    let handle_git_err = function
      | Ok x -> Lwt.return x
      | Error e -> Fmt.kstr Lwt.fail_with "%a" G.pp_error e

    type t = { config : Irmin.config; closed : bool ref; g : G.t; b : Branch.t }

    let branch_t t = t.b
    let contents_t t : 'a Contents.t = (t.closed, t.g)
    let node_t t : 'a Node.t = (contents_t t, (t.closed, t.g))
    let commit_t t : 'a Commit.t = (node_t t, (t.closed, t.g))
    let batch t f = f (contents_t t) (node_t t) (commit_t t)

    type config = {
      root : string;
      dot_git : string option;
      level : int option;
      buffers : int option;
      head : G.Reference.t option;
      bare : bool;
    }

    let config c =
      let module C = Irmin.Backend.Conf in
      let root = C.find_root c |> Option.value ~default:"." in
      let dot_git = C.get c Conf.Key.dot_git in
      let level = C.get c Conf.Key.level in
      let head = C.get c Conf.Key.head in
      let bare = C.get c Conf.Key.bare in
      let buffers = C.get c Conf.Key.buffers in
      { root; dot_git; level; head; buffers; bare }

    let fopt f = function None -> None | Some x -> Some (f x)

    let v conf =
      let { root; dot_git; head; bare; _ } = config conf in
      let dotgit = fopt Fpath.v dot_git in
      let root = Fpath.v root in
      let* g = G.v ?dotgit root >>= handle_git_err in
      let+ b = Branch.v ~head ~bare g in
      { g; b; closed = ref false; config = (conf :> Irmin.config) }

    let config t = t.config
    let close t = Branch.close t.b >|= fun () -> t.closed := true
  end

  module Remote = struct
    include Remote.Make (G) (S) (Schema.Branch)

    let v repo = Lwt.return repo.Repo.g
  end

  let git_of_repo r = r.Repo.g

  let repo_of_git ?head ?(bare = true) ?lock g =
    let+ b = Branch.v ?lock ~head ~bare g in
    {
      Repo.config = Irmin.Backend.Conf.empty Conf.spec;
      closed = ref false;
      g;
      b;
    }
end
OCaml

Innovation. Community. Security.