summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius Peter <marius.peter@tutanota.com>2025-03-16 19:12:26 +0100
committerMarius Peter <marius.peter@tutanota.com>2025-03-16 19:12:26 +0100
commit4d38a55e52bbb88cacb8c5f5a996c7cdbfcc75bb (patch)
treeed7d34d53e4a820c3a2cc7ce8c525ea9023d4225
parent1d1b8113e117be008573a82c5596ac1e25799307 (diff)
Moderate amount of progress today 💯
-rw-r--r--lib/config.ml2
-rw-r--r--lib/handlers.ml26
-rw-r--r--lib/views.ml101
3 files changed, 88 insertions, 41 deletions
diff --git a/lib/config.ml b/lib/config.ml
index d47101f..61810fa 100644
--- a/lib/config.ml
+++ b/lib/config.ml
@@ -1,2 +1,2 @@
-let git_directory = Filename.concat (Unix.getenv "HOME") "git"
+let git_directory = Filename.concat (Unix.getenv "HOME") "git.test"
let author = "Marius Peter"
diff --git a/lib/handlers.ml b/lib/handlers.ml
index 3211929..d50eca8 100644
--- a/lib/handlers.ml
+++ b/lib/handlers.ml
@@ -1,4 +1,3 @@
-(* Handlers for different routes *)
let ogit_root _req = Views.Ogit_root.render () |> Dream_html.respond
let repo_root req =
@@ -7,19 +6,22 @@ let repo_root req =
let repo_tree req =
let repo_name = Dream.param req "repo_name" in
- let dir_path = Dream.param req "**" in
+ let dir_path = Dream.query req "path" |> Option.value ~default:"" in
Views.Repo_tree.render repo_name dir_path |> Dream_html.respond
let repo_blob req =
let repo_name = Dream.param req "repo_name" in
- let blob_name = Dream.param req "blob_name" in
- Views.Repo_blob.render repo_name blob_name |> Dream_html.respond
+ let blob_path = Dream.query req "path" |> Option.value ~default:"" in
+ Views.Repo_blob.render repo_name blob_path |> Dream_html.respond
-(* Route definitions *)
-let all_handlers = [
- Dream.get "/" ogit_root;
- Dream.get "/:repo_name" repo_root;
- Dream.get "/:repo_name/tree/**" repo_tree;
- Dream.get "/:repo_name/blob/:blob_name" repo_blob;
- Dream.get "/static/**" (Dream.static "./lib/static");
-]
+let all_handlers =
+ [
+ Dream.get "/" ogit_root;
+ Dream.scope "/:repo_name" []
+ [
+ Dream.get "/" repo_root;
+ Dream.get "/tree" repo_tree;
+ Dream.get "/blob" repo_blob;
+ ];
+ Dream.get "/static/**" (Dream.static "./lib/static");
+ ]
diff --git a/lib/views.ml b/lib/views.ml
index d09892b..6621831 100644
--- a/lib/views.ml
+++ b/lib/views.ml
@@ -29,7 +29,8 @@ module Layout = struct
[
title [] "%s" head_data.page_title;
link [ rel "stylesheet"; href "/static/styles.css" ];
- link [ rel "icon"; type_ "image/x-icon"; href "/static/git_icon.svg"];
+ link
+ [ rel "icon"; type_ "image/x-icon"; href "/static/git_icon.svg" ];
];
body []
[
@@ -50,7 +51,7 @@ module Topnav = struct
let is_active = path = current_path in
let attrs = if is_active then [ id "active" ] else [] in
let url =
- if String.length path = 0 then Printf.sprintf "/%s" repo_path
+ if String.equal path "/" then Printf.sprintf "/%s/" repo_path
else Printf.sprintf "/%s/%s" repo_path path
in
li attrs [ a [ href "%s" url ] [ txt text ] ]
@@ -61,7 +62,7 @@ module Topnav = struct
ul []
@@ List.map li_of_a
[
- ("", "summary");
+ ("/", "summary");
("refs", "refs");
("log", "log");
("tree", "tree");
@@ -129,15 +130,14 @@ module Repo_tree = struct
open Dream_html
open HTML
- let full_path repo_path dir_path =
- Filename.concat (Filename.concat Config.git_directory repo_path) dir_path
+ let full_path repo_name dir_path =
+ Filename.concat (Filename.concat Config.git_directory repo_name) dir_path
(* Helper function to list contents of a given directory *)
- let ls_dir repo_path dir_path =
- let dir_full_path = full_path repo_path dir_path in
+ let ls_dir repo_name dir_path =
+ let dir_full_path = full_path repo_name dir_path in
try
- Sys.readdir dir_full_path
- |> Array.to_list
+ Sys.readdir dir_full_path |> Array.to_list
|> List.filter (fun name -> name <> ".git") (* Exclude .git *)
|> List.map (fun entry ->
let entry_rel_path = Filename.concat dir_path entry in
@@ -145,34 +145,70 @@ module Repo_tree = struct
(entry, entry_rel_path, Sys.is_directory full_entry_path))
|> List.sort (fun (a, _, is_dir_a) (b, _, is_dir_b) ->
match (is_dir_a, is_dir_b) with
- | true, false -> -1 (* Directories first *)
+ | true, false -> -1 (* Directories first *)
| false, true -> 1
| _ -> String.compare a b)
with Sys_error _ -> []
(* Function to create a link based on file type *)
- let link_for_entry repo_path (entry, entry_rel_path, is_dir) =
+ let link_for_entry repo_name (entry, entry_rel_path, is_dir) =
let link =
- if is_dir then Printf.sprintf "/%s/tree/%s" repo_path entry_rel_path
- else Printf.sprintf "/%s/blob/%s" repo_path entry_rel_path
+ if is_dir then Printf.sprintf "/%s/tree?path=%s" repo_name entry_rel_path
+ else Printf.sprintf "/%s/blob?path=%s" repo_name entry_rel_path
in
- li [] [ a [ href "%s" link ] [ txt "%s" entry ] ]
+ let display_name = if is_dir then entry ^ "/" else entry in
+ li [] [ a [ href "%s" link ] [ txt "%s" display_name ] ]
- (* Render function, now supporting nested directories *)
- let render repo_path dir_path =
- let title = Filename.concat repo_path dir_path in
- let subtitle = "Repository Files" in
+ (* Generate breadcrumb navigation for the directory path *)
+ let breadcrumb_navigation repo_name dir_path =
+ let parts = String.split_on_char '/' dir_path in
- let repo_entries = ls_dir repo_path dir_path in
+ let rec build_paths acc paths =
+ match paths with
+ | [] -> List.rev acc
+ | part :: rest ->
+ let new_path =
+ match acc with [] -> part | _ -> List.hd acc ^ "/" ^ part
+ in
+ build_paths (new_path :: acc) rest
+ in
+
+ let breadcrumb_links =
+ build_paths [] parts
+ |> List.mapi (fun i path ->
+ let display_name = List.nth parts i in
+ a
+ [ href "%s" (Printf.sprintf "/%s/tree?path=%s" repo_name path) ]
+ [ txt "%s" display_name ])
+ in
+
+ (* Manually intersperse " / " separators *)
+ let rec intersperse sep = function
+ | [] -> []
+ | [ x ] -> [ x ]
+ | x :: xs -> x :: txt sep :: intersperse sep xs
+ in
+
+ match breadcrumb_links with
+ | [] -> txt "/"
+ | _ -> span [] (intersperse " / " breadcrumb_links)
+
+ (* Render function *)
+ let render repo_name dir_path =
+ let title = repo_name in
+ (* Only display the repo name as the title *)
+ let subtitle = "Files" in
+
+ let repo_entries = ls_dir repo_name dir_path in
let content =
[
- h3 [] [ txt "%s" (Printf.sprintf "Contents of /%s" dir_path) ];
- ul [] (List.map (link_for_entry repo_path) repo_entries);
+ h3 [] [ breadcrumb_navigation repo_name dir_path ];
+ ul [] (List.map (link_for_entry repo_name) repo_entries);
]
in
let body_data =
- { title; subtitle; topnav = Topnav.repo repo_path "tree"; content }
+ { title; subtitle; topnav = Topnav.repo repo_name "tree"; content }
in
Layout.application body_data
end
@@ -187,7 +223,8 @@ module Repo_blob = struct
let read_blob repo_path blob_name =
let file_path = Filename.concat (full_path repo_path) blob_name in
try Some (In_channel.with_open_text file_path In_channel.input_all)
- with _ -> None (* Handle cases where the file doesn't exist or can't be read *)
+ with _ ->
+ None (* Handle cases where the file doesn't exist or can't be read *)
(* Render function *)
let render repo_path blob_name =
@@ -196,17 +233,25 @@ module Repo_blob = struct
match read_blob repo_path blob_name with
| Some content ->
- let content_display =
- pre [] [ code [] [ txt "%s" content ] ] (* Render as code block *)
- in
+ let content_display = pre [] [ code [] [ txt "%s" content ] ] in
let body_data =
- { title; subtitle; topnav = Topnav.repo repo_path "blob"; content = [content_display] }
+ {
+ title;
+ subtitle;
+ topnav = Topnav.repo repo_path "blob";
+ content = [ content_display ];
+ }
in
Layout.application body_data
| None ->
let error_message = p [] [ txt "Error: Unable to read file." ] in
let body_data =
- { title; subtitle; topnav = Topnav.repo repo_path "blob"; content = [error_message] }
+ {
+ title;
+ subtitle;
+ topnav = Topnav.repo repo_path "blob";
+ content = [ error_message ];
+ }
in
Layout.application body_data
end
Copyright 2019--2025 Marius PETER