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
open Import
module Make (G : Git.S) = struct
module Info = Irmin.Info.Default
module Raw = Git.Value.Make (G.Hash)
module Hash = Irmin.Hash.Make (G.Hash)
module Key = Irmin.Key.Of_hash (Hash)
type t = G.Value.Commit.t
type commit_key = Key.t [@@deriving irmin]
type node_key = Key.t [@@deriving irmin]
type hash = Hash.t [@@deriving irmin]
let info_of_git author message =
let id = author.Git.User.name in
let date, _ = author.Git.User.date in
Info.v ~author:id ~message date
let name_email name =
let name = String.trim name in
try
let i = String.rindex name ' ' in
let email = String.sub name (i + 1) (String.length name - i - 1) in
if
String.length email > 0
&& email.[0] = '<'
&& email.[String.length email - 1] = '>'
then
let email = String.sub email 1 (String.length email - 2) in
let name = String.trim (String.sub name 0 i) in
(name, email)
else (name, "irmin@openmirage.org")
with Not_found -> (name, "irmin@openmirage.org")
let of_git g =
let node = G.Value.Commit.tree g in
let parents = G.Value.Commit.parents g in
let author = G.Value.Commit.author g in
let message = G.Value.Commit.message g in
let message = Option.value ~default:"" message in
let info = info_of_git author message in
(info, node, parents)
let to_git info node parents =
let tree = node in
let parents = List.fast_sort G.Hash.compare parents in
let author =
let date = Info.date info in
let name, email = name_email (Info.author info) in
Git.User.{ name; email; date = (date, None) }
in
let message = Info.message info in
G.Value.Commit.make
~tree ~parents ~author ~committer:author
(if message = "" then None else Some message)
let v ~info ~node ~parents = to_git info node parents
let xnode g = G.Value.Commit.tree g
let node t = xnode t
let parents g = G.Value.Commit.parents g
let info g =
let author = G.Value.Commit.author g in
let message = Option.value ~default:"" (G.Value.Commit.message g) in
info_of_git author message
module C = Irmin.Commit.Make (Hash)
let of_c c = to_git (C.info c) (C.node c) (C.parents c)
let to_c t =
let info, node, parents = of_git t in
C.v ~info ~node ~parents
let to_bin t = Raw.to_raw (G.Value.commit t)
let encode_bin (t : t) k =
[%log.debug "Commit.encode_bin"];
k (to_bin t)
let decode_bin buf pos_ref =
[%log.debug "Commit.decode_bin"];
let off = !pos_ref in
match Raw.of_raw_with_header ~off buf with
| Ok (Git.Value.Commit t) ->
pos_ref := String.length buf;
t
| Ok _ -> failwith "wrong object kind"
| Error _ -> failwith "wrong object kind"
let size_of = Irmin.Type.Size.custom_dynamic ()
let t = Irmin.Type.map ~bin:(encode_bin, decode_bin, size_of) C.t of_c to_c
end
module Store (G : Git.S) = struct
module Info = Irmin.Info.Default
module Hash = Irmin.Hash.Make (G.Hash)
module Val = Make (G)
module V = struct
type t = G.Value.Commit.t
let type_eq = function `Commit -> true | _ -> false
let of_git = function Git.Value.Commit c -> Some c | _ -> None
let to_git c = G.Value.commit c
end
include Content_addressable.Check_closed (Content_addressable.Make (G) (V))
end