[OCaml] Mobile-friendly clone of cgit.
1
(** Git data access layer. *)
2
3
module Store = Git_unix.Store
4
5
type error =
6
| Bad_request of string
7
| Not_found of string
8
| Store_error of Store.error
9
| Internal of string
10
11
val pp_error : Format.formatter -> error -> unit
12
13
(** {1 Validation} *)
14
15
val is_valid_hash_hex : string -> bool
16
val is_valid_repo_name : string -> bool
17
18
(** {1 Repository discovery and context} *)
19
20
type repository_layout = { worktree : string; git_dir : string }
21
type repository
22
23
val repositories : Config.t -> (string list, error) result
24
25
type repo_info = { repo_name : string; description : string }
26
type fs_node = Repo of repo_info | Directory of string * fs_node list
27
28
val scan_project_root : Config.t -> (fs_node list, error) result
29
val open_repository : Config.t -> string -> (repository, error) Lwt_result.t
30
val repository_name : repository -> string
31
val repository_description : repository -> string
32
val close_repository : repository -> unit Lwt.t
33
34
val head_commit_date :
35
repository -> (int64 * Git.User.tz_offset option) option Lwt.t
36
37
val head_hash_hint : Config.t -> string -> string option
38
(** Cheaply resolve the commit hash that HEAD names, using plain file reads and
39
no object store. [None] means "could not tell cheaply" — fall back to
40
opening the repository rather than conclude anything. Intended as a cache
41
key: any new commit on the served branch changes the result. *)
42
43
(** {1 Repository metadata} *)
44
45
val default_repo_description : string
46
val short_hash : string -> string
47
48
(** {1 Commits} *)
49
50
module Commit : sig
51
type user = Git.User.t
52
53
type t = {
54
hash : string;
55
tree : string;
56
parents : string list;
57
author : user;
58
committer : user;
59
message : string option;
60
}
61
62
val of_id : repository -> string -> (t, error) Lwt_result.t
63
val recent_from : repository -> string -> int -> (t list, error) Lwt_result.t
64
65
val recent_matching :
66
?max_examined:int ->
67
repository ->
68
int ->
69
(t -> bool) ->
70
(t list * bool, error) Lwt_result.t
71
(** Walk history from HEAD, collecting up to [count] commits that satisfy the
72
predicate. The walk reads at most [max_examined] commits (default 5000),
73
so a rare predicate cannot traverse an entire large history per request.
74
The boolean is [true] when the walk stopped at that cap with history left
75
unexplored — older matches may then exist beyond the result. *)
76
end
77
78
(** {1 References} *)
79
80
module Reference : sig
81
type t = { name : string; hash : string }
82
83
val branch_name : string -> string option
84
val tag_name : string -> string option
85
val of_id : repository -> string -> (t, error) Lwt_result.t
86
end
87
88
(** {1 Entries and Trees} *)
89
90
module Entry : sig
91
type perm = Dir | File | Exec | Link | Submodule
92
type t = { hash : string; name : string; perm : perm }
93
end
94
95
module Tree : sig
96
type t = { entries : Entry.t list }
97
type tree_node = { entry : Entry.t; children : tree_node list option }
98
99
val head : repository -> (t, error) Lwt_result.t
100
val expand : repository -> t -> (tree_node list, error) Lwt_result.t
101
102
val find_path :
103
repository -> string -> ((string * string) list, error) Lwt_result.t
104
end
105
106
(** {1 Blobs} *)
107
108
module Blob : sig
109
type t = { content : string }
110
end
111
112
(** {1 Diffs} *)
113
114
module Diff : sig
115
include module type of Line_diff
116
117
val of_commit : repository -> Commit.t -> (file list, error) Lwt_result.t
118
end
119
120
(** {1 Composite lookups} *)
121
122
val blob_or_tree :
123
repository ->
124
string ->
125
([> `Blob of Blob.t | `Tree of Tree.t ], error) Lwt_result.t
126
127
val object_at_path :
128
repository ->
129
string ->
130
( [ `Blob of Blob.t | `Tree of Tree.t ] * (string * string) list,
131
error )
132
Lwt_result.t
133
(** Resolve a slash-separated file path against the HEAD tree. Returns the
134
object and the trail of [(name, hash)] pairs from the root to it. Walks one
135
tree per path segment, so it is cheaper than searching for a hash with
136
{!Tree.find_path}. An empty path is a [Bad_request]; a path that names
137
nothing is [Not_found]. *)
138
139
(** {1 Repository helpers} *)
140
141
module Readme : sig
142
type t = { name : string; content : string }
143
end
144
145
module Repo : sig
146
val readme : repository -> (Readme.t option, error) Lwt_result.t
147
end
148
149
(** {1 Root helpers} *)
150
151
val read_root_readme : Config.t -> Blob.t option
152
val scan_subdirectory : Config.t -> string -> (fs_node list, error) result
153
val read_subdir_readme : Config.t -> string -> Blob.t option
154
155
(** {1 For tests}
156
157
These helpers have no callers in the server. They are exported so the test
158
suite can exercise repository discovery directly. *)
159
160
val is_repository : string -> bool
161
162
val repository_layout_or_none : string -> repository_layout option
163
(** Locate a repository's worktree and git directory. Collapses both "not a
164
repository" and "could not be inspected" to [None]. *)
165
166
val read_description_file : string -> string
167
val fallback_branch_candidates : Config.t -> string list
168