[OCaml] Mobile-friendly clone of cgit.
Handle missing HEAD refs without assuming master
Changed files
lib/resolvers.ml
@@ -76,6 +76,56 @@
76
76
77
77
let short_hash hash = String.sub hash 0 8
78
78
79
Added:
let branch_ref name = Git.Reference.v ("refs/heads/" ^ name)
80
Added:
81
Added:
let fallback_branch_candidates () =
82
Added:
let add acc name =
83
Added:
if List.mem name acc then acc else acc @ [ name ]
84
Added:
in
85
Added:
let candidates = [] in
86
Added:
let candidates = add candidates config.default_branch in
87
Added:
let candidates = add candidates "main" in
88
Added:
add candidates "master"
89
Added:
90
Added:
let resolve_head_hash store =
91
Added:
let fail_store_error err =
92
Added:
Lwt_result.fail (`Msg (Fmt.str "%a" Store.pp_error err))
93
Added:
in
94
Added:
let rec try_references = function
95
Added:
| [] ->
96
Added:
let open Lwt.Syntax in
97
Added:
let* references = Store.Ref.list store in
98
Added:
let branches =
99
Added:
references
100
Added:
|> List.map fst
101
Added:
|> List.filter_map (fun reference ->
102
Added:
let name = Git.Reference.to_string reference in
103
Added:
if String.starts_with ~prefix:"refs/heads/" name then
104
Added:
Some (name, reference)
105
Added:
else None)
106
Added:
|> List.sort (fun (a, _) (b, _) -> String.compare a b)
107
Added:
in
108
Added:
let rec try_branches = function
109
Added:
| [] -> Lwt_result.fail (`Msg "no branch could be resolved for repository")
110
Added:
| (_, reference) :: rest ->
111
Added:
Lwt.bind (Store.Ref.resolve store reference) @@ function
112
Added:
| Ok hash -> Lwt_result.return hash
113
Added:
| Error (`Reference_not_found _) -> try_branches rest
114
Added:
| Error err -> fail_store_error err
115
Added:
in
116
Added:
try_branches branches
117
Added:
| reference :: rest ->
118
Added:
Lwt.bind (Store.Ref.resolve store reference) @@ function
119
Added:
| Ok hash -> Lwt_result.return hash
120
Added:
| Error (`Reference_not_found _) -> try_references rest
121
Added:
| Error err -> fail_store_error err
122
Added:
in
123
Added:
Lwt.bind (Store.Ref.resolve store Git.Reference.head) @@ function
124
Added:
| Ok hash -> Lwt_result.return hash
125
Added:
| Error (`Reference_not_found _) ->
126
Added:
try_references (List.map branch_ref (fallback_branch_candidates ()))
127
Added:
| Error err -> fail_store_error err
128
Added:
79
129
module Commit = struct
80
130
type user = Git.User.t
81
131
@@ -104,7 +154,7 @@
104
154
105
155
let head repo =
106
156
let* store = store repo in
107
Removed:
let* hash = Store.Ref.resolve store Git.Reference.head in
157
Added:
let* hash = resolve_head_hash store in
108
158
let id = hash |> Store.Hash.to_hex in
109
159
of_id repo id
110
160
@@ -219,7 +269,7 @@
219
269
220
270
let head repo =
221
271
let* store = store repo in
222
Removed:
let* hash = Store.Ref.resolve store Git.Reference.head in
272
Added:
let* hash = resolve_head_hash store in
223
273
Lwt_result.bind (Store.read store hash) @@ function
224
274
| Git.Value.Commit commit ->
225
275
let tree_id = Store.Value.Commit.tree commit |> Store.Hash.to_hex in
test/test_ogit.ml
@@ -68,6 +68,13 @@
68
68
assert (git_dir = Filename.concat clone ".git")
69
69
| None -> failwith "expected a non-bare repository layout"
70
70
71
Added:
let test_fallback_branch_candidates () =
72
Added:
let names = Ogit.Resolvers.fallback_branch_candidates () in
73
Added:
assert (List.length names >= 2);
74
Added:
assert (List.mem "main" names);
75
Added:
assert (List.mem "master" names);
76
Added:
assert (List.length (List.sort_uniq String.compare names) = List.length names)
77
Added:
71
78
let () =
72
79
assert (Ogit.Resolvers.is_valid_repo_name "project.git");
73
80
assert (Ogit.Resolvers.is_valid_repo_name "project");
@@ -96,4 +103,5 @@
96
103
test_config_round_trip ();
97
104
test_config_location ();
98
105
test_description_reader ();
99
Removed:
test_repository_layout ()
106
Added:
test_repository_layout ();
107
Added:
test_fallback_branch_candidates ()