diff options
| -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 | 
