[OCaml] Mobile-friendly clone of cgit.
fix traverse all parents to show full commit history
The commit walker previously only followed first-parent links, which caused commits reachable only through second parents of merge commits to be invisible. This affected roughly half the history in repos with merge commits. Replace the linear walk with a BFS that enqueues all parents, sorted by author date descending, with deduplication via a string set. This produces the same output as 'git log' (all ancestors in date order).
lib/resolvers.ml
@@ -295,21 +295,39 @@
295
295
of_hash repository hash
296
296
297
297
let recent_matching_from repository hash count predicate =
298
Removed:
let rec walk commits hash remaining =
299
Removed:
if remaining <= 0 then Lwt_result.return (List.rev commits)
298
Added:
(* BFS traversal following all parents, ordered by author date descending *)
299
Added:
let module S = Set.Make (String) in
300
Added:
let rec walk collected seen queue remaining =
301
Added:
if remaining <= 0 then Lwt_result.return (List.rev collected)
300
302
else
301
Removed:
let* commit = of_id repository hash in
302
Removed:
let commits, remaining =
303
Removed:
if predicate commit then (commit :: commits, remaining - 1)
304
Removed:
else (commits, remaining)
305
Removed:
in
306
Removed:
if remaining <= 0 then Lwt_result.return (List.rev commits)
307
Removed:
else
308
Removed:
match commit.parents with
309
Removed:
| parent_hash :: _ -> walk commits parent_hash remaining
310
Removed:
| [] -> Lwt_result.return (List.rev commits)
303
Added:
match queue with
304
Added:
| [] -> Lwt_result.return (List.rev collected)
305
Added:
| (_, h) :: rest ->
306
Added:
if S.mem h seen then walk collected seen rest remaining
307
Added:
else
308
Added:
let seen = S.add h seen in
309
Added:
let* commit = of_id repository h in
310
Added:
(* Enqueue all parents *)
311
Added:
let new_queue =
312
Added:
List.filter_map
313
Added:
(fun p ->
314
Added:
if S.mem p seen then None
315
Added:
else Some (commit.author.Git.User.date, p))
316
Added:
commit.parents
317
Added:
in
318
Added:
(* Merge into queue sorted by date descending *)
319
Added:
let queue =
320
Added:
List.merge
321
Added:
(fun ((a_ts, _), _) ((b_ts, _), _) -> Int64.compare b_ts a_ts)
322
Added:
rest new_queue
323
Added:
in
324
Added:
let collected, remaining =
325
Added:
if predicate commit then (commit :: collected, remaining - 1)
326
Added:
else (collected, remaining)
327
Added:
in
328
Added:
walk collected seen queue remaining
311
329
in
312
Removed:
walk [] hash count
330
Added:
walk [] S.empty [ ((Int64.max_int, None), hash) ] count
313
331
314
332
let recent_from repository hash count =
315
333
recent_matching_from repository hash count (Fun.const true)