summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius Peter <marius.peter@tutanota.com>2025-02-01 19:24:32 +0100
committerMarius Peter <marius.peter@tutanota.com>2025-02-01 19:24:32 +0100
commit6e8e49ba49beeeb63e1e027fc23e8883a1185109 (patch)
tree6a816fc986c6650959087f88e7fd63997efe003c
parent19875b1503f6e890975e50bdd88853b6e4d0caf4 (diff)
Reorganized everything.
Thank you DeepSeek!
-rw-r--r--bin/dune2
-rw-r--r--bin/main.ml7
-rw-r--r--lib/config.ml1
-rw-r--r--lib/dune5
-rw-r--r--lib/handlers.ml4
-rw-r--r--lib/handlers/dune4
-rw-r--r--lib/handlers/handlers.ml13
-rw-r--r--lib/static/styles.css27
-rw-r--r--lib/views.ml136
-rw-r--r--lib/views/dune4
-rw-r--r--lib/views/layouts.ml45
-rw-r--r--lib/views/ogit_root.ml12
-rw-r--r--lib/views/repo_root.ml41
13 files changed, 178 insertions, 123 deletions
diff --git a/bin/dune b/bin/dune
index 64f988c..864d145 100644
--- a/bin/dune
+++ b/bin/dune
@@ -1,4 +1,4 @@
(executable
(public_name ogit)
(name main)
- (libraries dream handlers))
+ (libraries ogit dream))
diff --git a/bin/main.ml b/bin/main.ml
index 7a4341f..895bfb8 100644
--- a/bin/main.ml
+++ b/bin/main.ml
@@ -2,7 +2,8 @@ let () =
Dream.run @@ Dream.logger
@@ Dream.router
[
- Dream.get "/" @@ Handlers.ogit_root;
- Dream.get "/:repo_name/" @@ Handlers.repo_root repo;
- (* Dream.get "/:repo_name/tree" Handlers.repo_tree; *)
+ Dream.get "/" (fun _ -> Ogit.Handlers.ogit_root ());
+ Dream.get "/:repo_name" (fun request ->
+ Ogit.Handlers.repo_root @@ Dream.param request "repo_name");
+ Dream.get "/static/**" (Dream.static "./lib/static");
]
diff --git a/lib/config.ml b/lib/config.ml
new file mode 100644
index 0000000..4aab858
--- /dev/null
+++ b/lib/config.ml
@@ -0,0 +1 @@
+let git_directory = Filename.concat (Unix.getenv "HOME") "git"
diff --git a/lib/dune b/lib/dune
new file mode 100644
index 0000000..c091495
--- /dev/null
+++ b/lib/dune
@@ -0,0 +1,5 @@
+(library
+ (name ogit)
+ (libraries dream dream-html lwt_ppx git-unix)
+ (preprocess
+ (pps lwt_ppx)))
diff --git a/lib/handlers.ml b/lib/handlers.ml
new file mode 100644
index 0000000..1f6d920
--- /dev/null
+++ b/lib/handlers.ml
@@ -0,0 +1,4 @@
+let ogit_root _ = Dream_html.respond @@ Views.Ogit_root.render ()
+
+let repo_root repo_name =
+ Dream_html.respond @@ Lwt_main.run @@ Views.Repo_root.render repo_name
diff --git a/lib/handlers/dune b/lib/handlers/dune
deleted file mode 100644
index 4bae840..0000000
--- a/lib/handlers/dune
+++ /dev/null
@@ -1,4 +0,0 @@
-(library
- (name handlers)
- (public_name ogit.handlers)
- (libraries dream views))
diff --git a/lib/handlers/handlers.ml b/lib/handlers/handlers.ml
deleted file mode 100644
index 564d563..0000000
--- a/lib/handlers/handlers.ml
+++ /dev/null
@@ -1,13 +0,0 @@
-let ogit_root _ = Dream_html.respond @@ Views.Ogit_root.render ()
-let repo_root repo = Dream_html.respond @@ Views.Repo.render repo
-
-(* let repo_tree request = *)
-(* let repo_name = Dream.param request "repo_name" in *)
-(* let repo_path = Filename.concat (Unix.getenv "HOME") ("git/" ^ repo_name) in *)
-(* let content = *)
-(* if Sys.file_exists repo_path && Sys.is_directory repo_path then *)
-(* let files = Helpers.File_helpers.list_files repo_path in *)
-(* "<h1>Browsing repository: " ^ repo_name ^ "</h1><ul>" ^ files ^ "</ul>" *)
-(* else "<h1>Repository not found: " ^ repo_name ^ "</h1>" *)
-(* in *)
-(* Dream.html (page_layout ~content) *)
diff --git a/lib/static/styles.css b/lib/static/styles.css
new file mode 100644
index 0000000..680a6b1
--- /dev/null
+++ b/lib/static/styles.css
@@ -0,0 +1,27 @@
+body {
+ font-family: sans-serif;
+}
+
+nav#top {
+ background-color: dimgray;
+}
+
+nav#top ul {
+ display: flex;
+ list-style-type: none;
+}
+
+nav#top ul li {
+ padding: 1em 0;
+}
+
+nav#top ul li a {
+ color: white;
+ text-decoration: none;
+ padding: 0.5em 1em;
+}
+
+nav#top ul li a:hover {
+ background-color: #555;
+ text-decoration: revert;
+}
diff --git a/lib/views.ml b/lib/views.ml
new file mode 100644
index 0000000..64b003e
--- /dev/null
+++ b/lib/views.ml
@@ -0,0 +1,136 @@
+type page_data = { title : string; main_content : Dream_html.node list }
+
+module Layout = struct
+ open Dream_html
+ open HTML
+
+ let header =
+ null
+ [
+ h1 [] [ txt "ogit" ];
+ h2 [] [ txt "A mobile-friendly Git repository viewer" ];
+ ]
+
+ let topnav =
+ nav
+ [ id "top" ]
+ [
+ ul []
+ [
+ li [] [ a [ href "/" ] [ txt "Home" ] ];
+ li [] [ a [ href "/" ] [ txt "Refs" ] ];
+ li [] [ a [ href "/" ] [ txt "Log" ] ];
+ li [] [ a [ href "/" ] [ txt "Tree" ] ];
+ li [] [ a [ href "/" ] [ txt "Commit" ] ];
+ li [] [ a [ href "/" ] [ txt "Diff" ] ];
+ ];
+ ]
+
+ let footer name =
+ let today = Unix.localtime (Unix.time ()) in
+ let year = today.Unix.tm_year + 1900 |> string_of_int in
+ let space = " " in
+ let footer_text = String.concat space [ "©"; year; name ] in
+ footer [] [ txt "%s" footer_text ]
+
+ let application page =
+ html []
+ [
+ head [] [ title [] "%s" page.title ];
+ link [ rel "stylesheet"; href "/static/styles.css" ];
+ body []
+ [
+ header;
+ topnav;
+ div [ id "main" ] page.main_content;
+ footer "Marius PETER";
+ ];
+ ]
+end
+
+module Ogit_root = struct
+ open Dream_html
+ open HTML
+
+ let repositories_in directory =
+ let repositories = Sys.readdir directory |> Array.to_list
+ and li_of_repo repo = li [] [ a [ href "%s" repo ] [ txt "%s" repo ] ] in
+ div [ id "repositories" ] [ ul [] @@ List.map li_of_repo repositories ]
+
+ let page_data =
+ {
+ title = "My repositories";
+ main_content = [ repositories_in Config.git_directory ];
+ }
+
+ let render () = Layout.application page_data
+end
+
+module Repo_root = struct
+ open Dream_html
+ open HTML
+ open Git
+ open Lwt.Infix
+
+ let page_promise repo_name =
+ let repo_path = Filename.concat Config.git_directory repo_name in
+
+ (* 1. Open the Git repository *)
+ let%lwt repo =
+ Git_unix.Store.v (Fpath.v repo_path) >>= function
+ | Ok repo -> Lwt.return repo
+ | Error _ -> Lwt.fail_with "Could not open the Git repository."
+ in
+
+ (* 2. Resolve HEAD to get the latest commit hash *)
+ let%lwt commit_hash =
+ Git_unix.Store.Ref.resolve repo Reference.head >>= function
+ | Ok hash -> Lwt.return hash
+ | Error _ -> Lwt.fail_with "Failed to resolve HEAD"
+ in
+
+ (* (\* 3. Read the commit *\) *)
+ (* let%lwt commit = *)
+ (* Commit.v repo commit_hash >>= function *)
+ (* | Ok commit -> Lwt.return commit *)
+ (* | Error _ -> Lwt.fail_with "Failed to read the commit." *)
+ (* in *)
+
+ (* (\* 4. Read the tree from the commit *\) *)
+ (* let%lwt tree = *)
+ (* Tree.v commit.Commit.tree >>= function *)
+ (* | Ok tree -> Lwt.return tree *)
+ (* | Error _ -> Lwt.fail_with "Failed to read the tree." *)
+ (* in *)
+
+ (* (\* 5. Generate HTML list items for each tree entry *\) *)
+ (* let entries = Tree.entries tree in *)
+ (* let items = *)
+ (* List.map *)
+ (* (fun entry -> *)
+ (* let icon = match entry.Tree.perm with `Dir -> "📁 " | _ -> "📄 " in *)
+ (* li [] [ a [ href "#" ] [ txt (icon ^ entry.Tree.name) ] ]) *)
+ (* entries *)
+ (* in *)
+
+ (* 6. Assemble the page *)
+ let main_content =
+ [
+ ul []
+ [ li [] [ txt "%s" (commit_hash |> Digestif.SHA1.to_raw_string) ] ];
+ ]
+ in
+ let page_data = { title = repo_name; main_content } in
+ Lwt.return (Layout.application page_data)
+
+ let render repo_name = page_promise repo_name >>= fun page -> Lwt.return page
+end
+
+module Repo_tree = struct
+ open Dream_html
+
+ let render repo_name =
+ let title = repo_name and main_content = [ txt "foobar" ] in
+ let page_data = { title; main_content } in
+ Layout.application page_data
+end
diff --git a/lib/views/dune b/lib/views/dune
deleted file mode 100644
index 2c9ab5e..0000000
--- a/lib/views/dune
+++ /dev/null
@@ -1,4 +0,0 @@
-(library
- (name views)
- (public_name ogit.views)
- (libraries dream-html git-unix))
diff --git a/lib/views/layouts.ml b/lib/views/layouts.ml
deleted file mode 100644
index d9def3c..0000000
--- a/lib/views/layouts.ml
+++ /dev/null
@@ -1,45 +0,0 @@
-open Dream_html
-open HTML
-
-let header =
- div []
- [
- h1 [] [ txt "ogit" ];
- h2 [] [ txt "A mobile-friendly Git repository viewer" ];
- ]
-
-let topnav =
- nav
- [ id "top" ]
- [
- ul []
- [
- li [] [ a [ href "/" ] [ txt "Home" ] ];
- li [] [ a [ href "/" ] [ txt "Refs" ] ];
- li [] [ a [ href "/" ] [ txt "Log" ] ];
- li [] [ a [ href "/" ] [ txt "Tree" ] ];
- li [] [ a [ href "/" ] [ txt "Commit" ] ];
- li [] [ a [ href "/" ] [ txt "Diff" ] ];
- ];
- ]
-
-let footer name =
- let today = Unix.localtime (Unix.time ()) in
- let year = string_of_int (today.Unix.tm_year + 1900) in
- let space = " " in
- let footer_text = String.concat space [ "©"; year; name ] in
- footer [] [ txt "%s" footer_text ]
-
-let application ?(page_title = "ogit") ?(head_content = null []) ~main_content
- () =
- html []
- [
- head [] [ title [] "%s" page_title; head_content ];
- body []
- [
- header;
- topnav;
- div [ id "main" ] [ main_content ];
- footer "Marius PETER";
- ];
- ]
diff --git a/lib/views/ogit_root.ml b/lib/views/ogit_root.ml
deleted file mode 100644
index ca8e870..0000000
--- a/lib/views/ogit_root.ml
+++ /dev/null
@@ -1,12 +0,0 @@
-open Dream_html
-open HTML
-
-let git_directory = Filename.concat (Unix.getenv "HOME") "git"
-
-let repositories_in directory =
- let repositories = Sys.readdir directory |> Array.to_list
- and li_of_repo repo = li [] [ a [ href "%s" repo ] [ txt "%s" repo ] ] in
- div [ id "repositories" ] [ ul [] @@ List.map li_of_repo repositories ]
-
-let main_content = null [ txt "Hello World!"; repositories_in git_directory ]
-let render = Layouts.application ~page_title:"My repositories" ~main_content
diff --git a/lib/views/repo_root.ml b/lib/views/repo_root.ml
deleted file mode 100644
index dd391d8..0000000
--- a/lib/views/repo_root.ml
+++ /dev/null
@@ -1,41 +0,0 @@
-open Dream_html
-open HTML
-open Git_unix
-
-let git_directory = Filename.concat (Unix.getenv "HOME") "git"
-
-let err_to_string err = Fmt.to_to_string Store.pp_error err
-
-let get_head_commit repo_path =
- Lwt_main.run (
- let open Lwt.Infix in
- match Git.Reference.of_string "HEAD" with
- | Error err ->
- Lwt.return (Error ("Invalid HEAD reference string: " ^ err_to_string err))
- | Ok head_ref_name ->
- Store.v (Fpath.v repo_path) >>= function
- | Error err ->
- Lwt.return (Error ("Failed to open repository: " ^ err_to_string err))
- | Ok store ->
- Store.Ref.resolve store head_ref_name >>= function
- | Error err ->
- Lwt.return (Error ("Failed to resolve HEAD: " ^ err_to_string err))
- | Ok head_oid -> Lwt.return (Ok head_oid)
- (* Git.Commit.v store head_oid >>= function *)
- (* | Error err -> *)
- (* Lwt.return (Error ("Failed to get commit from hash: " ^ err_to_string err)) *)
- (* | Ok commit -> *)
- (* Lwt.return (Ok commit) *)
- )
-
-let main_content =
- let open Lwt.Infix in
- Lwt.async (fun _ ->
- get_head_commit git_directory >>= function
- | Error msg ->
- Lwt.map (fun content -> [ p [] [ txt content ]]) (Error msg)
- | Ok head_oid ->
- Lwt.map (fun content -> [ p [] [ txt "HEAD commit hash: %s" content ]]) (Store.Hash.to_string head_oid)
- )
-
-let render = Layouts.application ~page_title:"My repositories" ~main_content
Copyright 2019--2025 Marius PETER