[OCaml] Mobile-friendly clone of cgit.
refactor address deep good-taste review findings
- Add lib/list_ext.ml with take/drop helpers; replace all 6 List.filteri-as-take/drop patterns in handlers.ml and repo.ml - Replace 4-level nested match in language_of_content with a local ( <|> ) lazy option combinator for flat chaining - Routes.dispatch now returns None for malformed action URLs (e.g. /repo/commit/ without a hash) instead of silently falling back to Summary — these properly 404 - Replace nested match for page query param with >>= pipeline
Changed files
lib/handlers.ml
@@ -93,10 +93,10 @@
93
93
let author = Dream.query request "author" in
94
94
let committer = Dream.query request "committer" in
95
95
let page =
96
Removed:
match Dream.query request "page" with
97
Removed:
| None -> 1
98
Removed:
| Some s -> (
99
Removed:
match int_of_string_opt s with Some p when p > 0 -> p | _ -> 1)
96
Added:
let ( >>= ) = Option.bind in
97
Added:
Dream.query request "page" >>= int_of_string_opt
98
Added:
>>= (fun p -> if p > 0 then Some p else None)
99
Added:
|> Option.value ~default:1
100
100
in
101
101
let offset = (page - 1) * page_size in
102
102
(* Fetch one beyond orphan threshold to detect whether more exist *)
@@ -107,8 +107,7 @@
107
107
in
108
108
let total = List.length all_commits in
109
109
let after_offset =
110
Removed:
if offset >= total then []
111
Removed:
else List.filteri (fun i _ -> i >= offset) all_commits
110
Added:
if offset >= total then [] else List_ext.drop offset all_commits
112
111
in
113
112
let remaining = List.length after_offset in
114
113
(* Avoid a final page with fewer than 10 items — absorb them into this
@@ -117,9 +116,7 @@
117
116
if remaining > page_size && remaining <= page_size + 10 then remaining
118
117
else page_size
119
118
in
120
Removed:
let page_commits =
121
Removed:
List.filteri (fun i _ -> i < effective_size) after_offset
122
Removed:
in
119
Added:
let page_commits = List_ext.take effective_size after_offset in
123
120
let has_next = remaining > effective_size in
124
121
let has_prev = page > 1 in
125
122
Views.Repo.commits ?filter_type ?author ?committer ~page ~has_prev ~has_next
@@ -136,7 +133,7 @@
136
133
if remaining > page_size && remaining <= page_size + 10 then remaining
137
134
else page_size
138
135
in
139
Removed:
let page_commits = List.filteri (fun i _ -> i < effective_size) commits in
136
Added:
let page_commits = List_ext.take effective_size commits in
140
137
let has_next = remaining > effective_size in
141
138
Views.Repo.commits ~page:1 ~has_prev:false ~has_next context page_commits
142
139
lib/list_ext.ml
@@ -0,0 +1,13 @@
1
Added:
(* -*- mode: tuareg; -*- *)
2
Added:
3
Added:
(** List utilities not in the OCaml 5.2 stdlib. *)
4
Added:
5
Added:
let rec take n = function
6
Added:
| _ when n <= 0 -> []
7
Added:
| [] -> []
8
Added:
| x :: rest -> x :: take (n - 1) rest
9
Added:
10
Added:
let rec drop n = function
11
Added:
| l when n <= 0 -> l
12
Added:
| [] -> []
13
Added:
| _ :: rest -> drop (n - 1) rest
lib/routes.ml
@@ -79,19 +79,19 @@
79
79
else
80
80
let action =
81
81
match (seg, rest) with
82
Removed:
| "summary", _ -> Summary
83
Removed:
| "commits", [] -> Commits_page
84
Removed:
| "commits", [ branch ] -> Commits_for_branch branch
85
Removed:
| "commit", [ hash ] -> Commit_detail hash
86
Removed:
| "files", _ -> Files_page
87
Removed:
| "file", [ hash ] -> File_detail hash
88
Removed:
| "branches", _ -> Branches_page
89
Removed:
| "tags", _ -> Tags_page
90
Removed:
| "README", _ -> Readme_page
91
Removed:
| "raw", [ hash ] -> Raw hash
92
Removed:
| _ -> Summary
82
Added:
| "summary", _ -> Some Summary
83
Added:
| "commits", [] -> Some Commits_page
84
Added:
| "commits", [ branch ] -> Some (Commits_for_branch branch)
85
Added:
| "commit", [ hash ] -> Some (Commit_detail hash)
86
Added:
| "files", _ -> Some Files_page
87
Added:
| "file", [ hash ] -> Some (File_detail hash)
88
Added:
| "branches", _ -> Some Branches_page
89
Added:
| "tags", _ -> Some Tags_page
90
Added:
| "README", _ -> Some Readme_page
91
Added:
| "raw", [ hash ] -> Some (Raw hash)
92
Added:
| _ -> None
93
93
in
94
Removed:
Some (repo, action)
94
Added:
Option.map (fun a -> (repo, a)) action
95
95
| seg :: rest -> find_split (seg :: repo_acc) rest
96
96
in
97
97
find_split [] segments
lib/views/repo.ml
@@ -231,25 +231,21 @@
231
231
let len = List.length lines in
232
232
let first_lines =
233
233
let n = min 5 len in
234
Removed:
List.filteri (fun i _ -> i < n) lines
234
Added:
List_ext.take n lines
235
235
in
236
236
let last_lines =
237
237
let start = max 0 (len - 5) in
238
Removed:
List.filteri (fun i _ -> i >= start) lines
238
Added:
List_ext.drop start lines
239
239
in
240
240
let try_lines detector lines = List.find_map detector lines in
241
Added:
let ( <|> ) a b = match a with Some _ -> a | None -> b () in
241
242
match first_lines with
242
243
| [] -> None
243
Removed:
| first :: _ -> (
244
Removed:
match language_of_shebang first with
245
Removed:
| Some _ as result -> result
246
Removed:
| None -> (
247
Removed:
match try_lines language_of_emacs_prop first_lines with
248
Removed:
| Some _ as result -> result
249
Removed:
| None -> (
250
Removed:
match try_lines language_of_vim_modeline first_lines with
251
Removed:
| Some _ as result -> result
252
Removed:
| None -> try_lines language_of_vim_modeline last_lines)))
244
Added:
| first :: _ ->
245
Added:
( ( language_of_shebang first <|> fun () ->
246
Added:
try_lines language_of_emacs_prop first_lines )
247
Added:
<|> fun () -> try_lines language_of_vim_modeline first_lines )
248
Added:
<|> fun () -> try_lines language_of_vim_modeline last_lines
253
249
254
250
let page_title context = context.repo ^ " — " ^ context.description
255
251
@@ -459,9 +455,7 @@
459
455
let total = List.length children in
460
456
let displayed, overflow =
461
457
if total <= max_display then (children, 0)
462
Removed:
else
463
Removed:
( List.filteri (fun i _ -> i < max_display) children,
464
Removed:
total - max_display )
458
Added:
else (List_ext.take max_display children, total - max_display)
465
459
in
466
460
let overflow_item =
467
461
if overflow = 0 then []