diff options
author | Marius Peter <marius.peter@tutanota.com> | 2025-02-01 19:24:32 +0100 |
---|---|---|
committer | Marius Peter <marius.peter@tutanota.com> | 2025-02-01 19:24:32 +0100 |
commit | 6e8e49ba49beeeb63e1e027fc23e8883a1185109 (patch) | |
tree | 6a816fc986c6650959087f88e7fd63997efe003c | |
parent | 19875b1503f6e890975e50bdd88853b6e4d0caf4 (diff) |
Reorganized everything.
Thank you DeepSeek!
-rw-r--r-- | bin/dune | 2 | ||||
-rw-r--r-- | bin/main.ml | 7 | ||||
-rw-r--r-- | lib/config.ml | 1 | ||||
-rw-r--r-- | lib/dune | 5 | ||||
-rw-r--r-- | lib/handlers.ml | 4 | ||||
-rw-r--r-- | lib/handlers/dune | 4 | ||||
-rw-r--r-- | lib/handlers/handlers.ml | 13 | ||||
-rw-r--r-- | lib/static/styles.css | 27 | ||||
-rw-r--r-- | lib/views.ml | 136 | ||||
-rw-r--r-- | lib/views/dune | 4 | ||||
-rw-r--r-- | lib/views/layouts.ml | 45 | ||||
-rw-r--r-- | lib/views/ogit_root.ml | 12 | ||||
-rw-r--r-- | lib/views/repo_root.ml | 41 |
13 files changed, 178 insertions, 123 deletions
@@ -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 |