Great work today, again!

Commit
346d17a1f4c78a05fb1fe010eb1a9e646c8b04a3
Author
Marius Peter <marius.peter@tutanota.com>
Author date
Committer
Marius Peter <marius.peter@tutanota.com>
Committer date
Changed files
bin/main.ml
index 74712e1d..5fcd6cfa 100644..100644
@@ -1,13 +1,1 @@
1 Removed: let () =
2 Removed: Dream.run @@ Dream.logger
3 Removed: @@ Dream.router
4 Removed: [
5 Removed: Dream.get "/" (fun _req -> Ogit.Handlers.ogit_root _req);
6 Removed: Dream.get "/:repo_name" (fun req ->
7 Removed: let repo_name = Dream.param req "repo_name" in
8 Removed: Ogit.Handlers.repo_root repo_name);
9 Removed: Dream.get "/:repo_name/tree" (fun req ->
10 Removed: let repo_name = Dream.param req "repo_name" in
11 Removed: Ogit.Handlers.repo_tree repo_name);
12 Removed: Dream.get "/static/**" (Dream.static "./lib/static");
13 Removed: ]
1 Added: let () = Dream.run @@ Dream.logger @@ Dream.router Ogit.Handlers.all_handlers
lib/dune
index 076d7c62..3963ffd4 100644..100644
@@ -1,5 +1,5 @@
1 1 (library
2 2 (name ogit)
3 Removed: (libraries unix dream dream-html git git-unix)
3 Added: (libraries dream dream-html git git-unix)
4 4 (preprocess
5 5 (pps lwt_ppx)))
lib/handlers.ml
index 46df3541..3211929d 100644..100644
@@ -1,3 +1,25 @@
1 Removed: let ogit_root _ = Views.Ogit_root.render () |> Dream_html.respond
2 Removed: let repo_root repo_name = Views.Repo_root.render repo_name |> Dream_html.respond
3 Removed: let repo_tree repo_name = Views.Repo_tree.render repo_name |> Dream_html.respond
1 Added: (* Handlers for different routes *)
2 Added: let ogit_root _req = Views.Ogit_root.render () |> Dream_html.respond
3 Added:
4 Added: let repo_root req =
5 Added: let repo_name = Dream.param req "repo_name" in
6 Added: Views.Repo_root.render repo_name |> Dream_html.respond
7 Added:
8 Added: let repo_tree req =
9 Added: let repo_name = Dream.param req "repo_name" in
10 Added: let dir_path = Dream.param req "**" in
11 Added: Views.Repo_tree.render repo_name dir_path |> Dream_html.respond
12 Added:
13 Added: let repo_blob req =
14 Added: let repo_name = Dream.param req "repo_name" in
15 Added: let blob_name = Dream.param req "blob_name" in
16 Added: Views.Repo_blob.render repo_name blob_name |> Dream_html.respond
17 Added:
18 Added: (* Route definitions *)
19 Added: let all_handlers = [
20 Added: Dream.get "/" ogit_root;
21 Added: Dream.get "/:repo_name" repo_root;
22 Added: Dream.get "/:repo_name/tree/**" repo_tree;
23 Added: Dream.get "/:repo_name/blob/:blob_name" repo_blob;
24 Added: Dream.get "/static/**" (Dream.static "./lib/static");
25 Added: ]
lib/static/styles.css
index de2c3dbf..680a6b17 100644..100644
@@ -1,29 +1,18 @@
1 Removed: @import url("fonts/Inter-4.1/web/inter.css");
2 Removed:
3 1 body {
4 Removed: font-family: Inter, sans-serif;
5 Removed: max-width: 50em;
6 Removed: margin: auto;
7 Removed: padding: 0 1em;
8 Removed: background-color: #181818;
9 Removed: color: white;
2 Added: font-family: sans-serif;
10 3 }
11 4
12 5 nav#top {
13 Removed: background-color: black;
14 Removed: border-radius: 0.25rem;
6 Added: background-color: dimgray;
15 7 }
16 8
17 9 nav#top ul {
18 Removed: display: flex;
19 Removed: flex-wrap: wrap;
10 Added: display: flex;
20 11 list-style-type: none;
21 Removed: padding: 0;
22 12 }
23 13
24 14 nav#top ul li {
25 Removed: padding: 0.5em 0;
26 Removed: border-radius: 0.25rem;
15 Added: padding: 1em 0;
27 16 }
28 17
29 18 nav#top ul li a {
@@ -33,39 +22,6 @@
33 22 }
34 23
35 24 nav#top ul li a:hover {
36 Removed: background-color: white;
37 Removed: color: black;
38 Removed: }
39 Removed:
40 Removed: nav#top ul li#active {
41 Removed: border-radius: 0.25rem;
42 Removed: background-color: rgb(194, 79, 30);
43 Removed: }
44 Removed:
45 Removed: nav#top ul li#active a:hover {
46 Removed: border-radius: 0.25rem;
47 Removed: background-color: rgb(132, 40, 0);
48 Removed: color: white;
49 Removed: }
50 Removed:
51 Removed: div#main ul {
52 Removed: padding-left: 0;
53 Removed: list-style: none;
54 Removed: }
55 Removed:
56 Removed: div#main ul li {
57 Removed: border: 1px solid #303030;
58 Removed: }
59 Removed:
60 Removed: div#main ul li a {
61 Removed: display: block;
62 Removed: color: white;
63 Removed: text-decoration: none;
64 Removed: padding: 0.5em;
65 Removed: }
66 Removed:
67 Removed: div#main a:hover {
68 Removed: background-color: white;
69 Removed: color: black;
25 Added: background-color: #555;
70 26 text-decoration: revert;
71 27 }
lib/views.ml
index 2d116745..d09892b1 100644..100644
@@ -29,6 +29,7 @@
29 29 [
30 30 title [] "%s" head_data.page_title;
31 31 link [ rel "stylesheet"; href "/static/styles.css" ];
32 Added: link [ rel "icon"; type_ "image/x-icon"; href "/static/git_icon.svg"];
32 33 ];
33 34 body []
34 35 [
@@ -68,30 +69,6 @@
68 69 ("diff", "diff");
69 70 ];
70 71 ]
71 Removed:
72 Removed: (* let li_of_a (path, text) = *)
73 Removed: (* let is_active = path = current_path in *)
74 Removed: (* li (if is_active then [ id "active" ] else []) in *)
75 Removed: (* let link_of_path = *)
76 Removed: (* if String.length path = 0 then Printf.sprintf "/%s" repo_path *)
77 Removed: (* else Printf.sprintf "/%s/%s" repo_path path *)
78 Removed: (* in *)
79 Removed: (* li [ id "active" ] [ a [ href "%s" link_of_path ] [ txt text ] ] *)
80 Removed: (* in *)
81 Removed: (* nav *)
82 Removed: (* [ id "top" ] *)
83 Removed: (* [ *)
84 Removed: (* ul [] *)
85 Removed: (* @@ List.map li_of_a *)
86 Removed: (* [ *)
87 Removed: (* ("", "summary"); *)
88 Removed: (* ("refs", "refs"); *)
89 Removed: (* ("log", "log"); *)
90 Removed: (* ("tree", "tree"); *)
91 Removed: (* ("commit", "commit"); *)
92 Removed: (* ("diff", "diff"); *)
93 Removed: (* ]; *)
94 Removed: (* ] *)
95 72 end
96 73
97 74 module Ogit_root = struct
@@ -123,13 +100,6 @@
123 100 open Dream_html
124 101 open HTML
125 102
126 Removed: (* let href_for_git_object kind identifier = *)
127 Removed: (* let open Printf in *)
128 Removed: (* href "%s" @@ *)
129 Removed: (* match kind with *)
130 Removed: (* | `Branch -> sprintf "/tree/%s" identifier *)
131 Removed: (* | `Commit -> sprintf "/commit/%s" identifier *)
132 Removed:
133 103 let render repo_path =
134 104 let title = repo_path in
135 105 let subtitle = Filename.concat Config.git_directory repo_path in
@@ -159,41 +129,84 @@
159 129 open Dream_html
160 130 open HTML
161 131
162 Removed: let full_path repo_path = Filename.concat Config.git_directory repo_path
132 Added: let full_path repo_path dir_path =
133 Added: Filename.concat (Filename.concat Config.git_directory repo_path) dir_path
163 134
164 Removed: (* Helper function to list top-level files and directories *)
165 Removed: let ls_repo repo_path =
135 Added: (* Helper function to list contents of a given directory *)
136 Added: let ls_dir repo_path dir_path =
137 Added: let dir_full_path = full_path repo_path dir_path in
166 138 try
167 Removed: Sys.readdir (full_path repo_path)
139 Added: Sys.readdir dir_full_path
168 140 |> Array.to_list
169 141 |> List.filter (fun name -> name <> ".git") (* Exclude .git *)
170 Removed: |> List.sort String.compare
142 Added: |> List.map (fun entry ->
143 Added: let entry_rel_path = Filename.concat dir_path entry in
144 Added: let full_entry_path = Filename.concat dir_full_path entry in
145 Added: (entry, entry_rel_path, Sys.is_directory full_entry_path))
146 Added: |> List.sort (fun (a, _, is_dir_a) (b, _, is_dir_b) ->
147 Added: match (is_dir_a, is_dir_b) with
148 Added: | true, false -> -1 (* Directories first *)
149 Added: | false, true -> 1
150 Added: | _ -> String.compare a b)
171 151 with Sys_error _ -> []
172 152
173 153 (* Function to create a link based on file type *)
174 Removed: let link_for_entry repo_path entry =
175 Removed: let entry_path = Filename.concat (full_path repo_path) entry in
176 Removed: if Sys.is_directory entry_path then
177 Removed: a
178 Removed: [ href "%s" @@ Printf.sprintf "/%s/tree/%s" repo_path entry ]
179 Removed: [ txt "%s" (entry ^ "/") ]
180 Removed: else
181 Removed: a
182 Removed: [ href "%s" @@ Printf.sprintf "/%s/blob/%s" repo_path entry ]
183 Removed: [ txt "%s" entry ]
154 Added: let link_for_entry repo_path (entry, entry_rel_path, is_dir) =
155 Added: let link =
156 Added: if is_dir then Printf.sprintf "/%s/tree/%s" repo_path entry_rel_path
157 Added: else Printf.sprintf "/%s/blob/%s" repo_path entry_rel_path
158 Added: in
159 Added: li [] [ a [ href "%s" link ] [ txt "%s" entry ] ]
184 160
185 Removed: let li_of_entry repo_path entry = li [] [ link_for_entry repo_path entry ]
161 Added: (* Render function, now supporting nested directories *)
162 Added: let render repo_path dir_path =
163 Added: let title = Filename.concat repo_path dir_path in
164 Added: let subtitle = "Repository Files" in
186 165
187 Removed: (* Render function *)
188 Removed: let render repo_path =
189 Removed: let title = repo_path in
190 Removed: let subtitle = "Files" in
166 Added: let repo_entries = ls_dir repo_path dir_path in
167 Added: let content =
168 Added: [
169 Added: h3 [] [ txt "%s" (Printf.sprintf "Contents of /%s" dir_path) ];
170 Added: ul [] (List.map (link_for_entry repo_path) repo_entries);
171 Added: ]
172 Added: in
191 173
192 Removed: let repo_entries = ls_repo repo_path in
193 Removed: let content = [ ul [] (List.map (li_of_entry repo_path) repo_entries) ] in
194 Removed:
195 174 let body_data =
196 175 { title; subtitle; topnav = Topnav.repo repo_path "tree"; content }
197 176 in
198 177 Layout.application body_data
178 Added: end
179 Added:
180 Added: module Repo_blob = struct
181 Added: open Dream_html
182 Added: open HTML
183 Added:
184 Added: let full_path repo_path = Filename.concat Config.git_directory repo_path
185 Added:
186 Added: (* Read the contents of a file *)
187 Added: let read_blob repo_path blob_name =
188 Added: let file_path = Filename.concat (full_path repo_path) blob_name in
189 Added: try Some (In_channel.with_open_text file_path In_channel.input_all)
190 Added: with _ -> None (* Handle cases where the file doesn't exist or can't be read *)
191 Added:
192 Added: (* Render function *)
193 Added: let render repo_path blob_name =
194 Added: let title = blob_name in
195 Added: let subtitle = "File Contents" in
196 Added:
197 Added: match read_blob repo_path blob_name with
198 Added: | Some content ->
199 Added: let content_display =
200 Added: pre [] [ code [] [ txt "%s" content ] ] (* Render as code block *)
201 Added: in
202 Added: let body_data =
203 Added: { title; subtitle; topnav = Topnav.repo repo_path "blob"; content = [content_display] }
204 Added: in
205 Added: Layout.application body_data
206 Added: | None ->
207 Added: let error_message = p [] [ txt "Error: Unable to read file." ] in
208 Added: let body_data =
209 Added: { title; subtitle; topnav = Topnav.repo repo_path "blob"; content = [error_message] }
210 Added: in
211 Added: Layout.application body_data
199 212 end