diff options
| author | Marius Peter <marius.peter@tutanota.com> | 2025-06-21 12:09:35 +0200 | 
|---|---|---|
| committer | Marius Peter <marius.peter@tutanota.com> | 2025-06-21 12:09:35 +0200 | 
| commit | 034ae69f2f22d7957386e73b3c42053fbf0cdfb2 (patch) | |
| tree | b991f59a492b62b059029aa7365547e826c07416 /lib | |
| parent | 6e07594aace8bc2c6f99219b4022a68291201aad (diff) | |
Refactor resolvers.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/handlers.ml | 19 | ||||
| -rw-r--r-- | lib/resolvers.ml | 258 | ||||
| -rw-r--r-- | lib/views.ml | 52 | 
3 files changed, 175 insertions, 154 deletions
| diff --git a/lib/handlers.ml b/lib/handlers.ml index 871931c..e63e911 100644 --- a/lib/handlers.ml +++ b/lib/handlers.ml @@ -13,36 +13,37 @@ module Repo = struct    let summary req =      let repo = Dream.param req "repo" in -    let* branches = Resolvers.all_branches repo in -    let* commits = Resolvers.recent_commits repo 10 in +    (* let* branches = Resolvers.Branch.all repo in *) +    (* let* commits = Resolvers.Commit.recent repo 10 in *) +    let* commits = Resolvers.Commit.head repo in      let authors = [ "John Pork"; "Sebastian Jellybean" ] in -    Views.Repo.summary repo branches commits authors +    Views.Repo.summary repo () [commits] authors    let log req =      let repo = Dream.param req "repo" in -    let* commits = Resolvers.recent_commits repo 100 in +    let* commits = Resolvers.Commit.recent repo 100 in      Views.Repo.log repo commits    let files_at_head req =      let repo = Dream.param req "repo" in -    let* tree = Resolvers.head_tree repo in +    let* tree = Resolvers.Tree.head repo in      Views.Repo.files repo tree    let file_id req =      let repo = Dream.param req "repo" in      let id = Dream.param req "repo" in -    let* blob = Resolvers.blob_of_id repo id in +    let* blob = Resolvers.Blob.of_id repo id in      Views.Repo.file repo blob    let refs req =      let repo = Dream.param req "repo" in -    let* branches = Resolvers.all_branches repo in -    Views.Repo.refs repo branches +    (* let* branches = Resolvers.Branch.all repo in *) +    Views.Repo.refs repo ()    let commit req =      let repo = Dream.param req "repo" in      let id = Dream.param req "id" in -    let* commit = Resolvers.commit_of_id repo id in +    let* commit = Resolvers.Commit.of_id repo id in      Views.Repo.commit repo commit  end diff --git a/lib/resolvers.ml b/lib/resolvers.ml index af8fd8b..9baa116 100644 --- a/lib/resolvers.ml +++ b/lib/resolvers.ml @@ -2,134 +2,152 @@  module Store = Git_unix.Store  open Lwt_result.Syntax -open Lwt_result.Infix + +(* open Lwt_result.Infix *)  open Config  let full_path path = Filename.concat config.git_project_root path  let store repo = -  let path = Fpath.v @@ full_path repo in +  let path = full_path repo |> Fpath.v in    Store.v ~dotgit:path path  let repo_description repo =    let description_path = Filename.concat (full_path repo) "description" in    In_channel.with_open_text description_path In_channel.input_all -type user = Git.User.t - -type commit = { -  hash : string; -  short_hash : string; -  parents : string list; -  author : user; -  message : string option; -} - -let to_commit store hash = -  Store.read store hash >>= function -  | Git.Value.Commit c -> -      let hash = Store.Hash.to_hex hash in -      Lwt_result.return -        { -          hash; -          short_hash = String.sub hash 0 8; -          parents = Store.Value.Commit.parents c |> List.map Store.Hash.to_hex; -          author = Store.Value.Commit.author c; -          message = Store.Value.Commit.message c; -        } -  | _ -> Lwt_result.fail (`Msg "value is not a commit") - -let commit_of_id repo id = -  let* store = store repo in -  let hash = Store.Hash.of_hex id in -  to_commit store hash - -let recent_commits repo n = -  let* store = store repo in -  let* head = Store.Ref.resolve store Git.Reference.head in -  let rec walk acc hash count = -    if count = 0 then Lwt_result.return (List.rev acc) -    else -      let* commit = to_commit store hash in -      match commit.parents with -      | parent :: _ -> -          walk (commit :: acc) (Store.Hash.of_hex parent) (count - 1) -      | [] -> Lwt_result.return (List.rev (commit :: acc)) -  in -  walk [] head n - -type branch = { hash : string; name : string } - -let all_branches repo = -  let* store = store repo in -  let open Lwt.Syntax in -  let* refs = Store.Ref.list store in -  let branches = -    List.map -      (fun (reference, hash) -> -        let name = Git.Reference.to_string reference in -        let hash = Store.Hash.to_hex hash in -        { name; hash }) -      refs -  in -  Lwt_result.return branches - -type tree_entry = { -  hash : string; -  short_hash : string; -  name : string; -  perm : int; -} - -type tree = { hash : string; short_hash : string; entries : tree_entry list } -type blob = { content : string } - -let to_entry (entry : Store.Value.Tree.entry) = -  let perm = -    match entry.perm with -    | `Commit -> 0o160000 -    | `Dir -> 0o040000 -    | `Everybody -> 0o100664 -    | `Exec -> 0o100755 -    | `Link -> 0o120000 -    | `Normal -> 0o100644 -  in -  let hash = Store.Hash.to_hex entry.node in -  let short_hash = String.sub hash 0 8 in -  { hash; short_hash; name = entry.name; perm } - -let to_tree store hash = -  Store.read store hash >>= function -  | Git.Value.Tree tree -> -      let hash = Store.Hash.to_hex hash in -      let short_hash = String.sub hash 0 8 in -      let entries = Store.Value.Tree.to_list tree |> List.map to_entry in -      Lwt_result.return { hash; short_hash; entries } -  | _ -> Lwt_result.fail (`Msg "value is not a tree") - -let to_blob store hash = -  Store.read store hash >>= function -  | Git.Value.Blob blob -> -      let content = Store.Value.Blob.to_string blob in -      Lwt_result.return { content } -  | _ -> Lwt_result.fail (`Msg "value is not a blob") - -let head_tree repo = -  let* store = store repo in -  let* hash = -    Store.Ref.resolve store Git.Reference.head >>= Store.read store >>= function -    | Git.Value.Commit commit -> -        Store.Value.Commit.tree commit |> Lwt_result.return -    | _ -> `Msg "no head tree id" |> Lwt_result.fail -  in -  to_tree store hash - -let tree_of_id repo id = -  let* store = store repo in -  let hash = Store.Hash.of_hex id in -  to_tree store hash - -let blob_of_id repo id = -  let* store = store repo in -  let hash = Store.Hash.of_hex id in -  to_blob store hash +let short_hash hash = String.sub hash 0 8 + +module Commit = struct +  type user = Git.User.t + +  type t = { +    hash : string; +    parents : string list; +    author : user; +    message : string option; +  } + +  let to_t c = +    let open Store.Value in +    { +      hash = Store.Value.Commit.digest c |> Store.Hash.to_hex; +      parents = Commit.parents c |> List.map Store.Hash.to_hex; +      author = Commit.author c; +      message = Commit.message c; +    } + +  let of_id repo id = +    let* store = store repo in +    let hash = Store.Hash.of_hex id in +    Store.read store hash +    |> Lwt_result.map @@ function +       | Git.Value.Commit commit -> to_t commit +       | _ -> failwith (id ^ " does not point to a commit object") + +  let head repo = +    let* store = store repo in +    let* hash = Store.Ref.resolve store Git.Reference.head in +    let id = hash |> Store.Hash.to_hex in +    of_id repo id + +  let recent repo n = +    let* head_commit = head repo in +    let rec walk acc hash count = +      if count = 0 then Lwt_result.return (List.rev acc) +      else +        let* commit = of_id repo hash in +        match commit.parents with +        | parent_hash :: _ -> walk (commit :: acc) parent_hash (count - 1) +        | [] -> Lwt_result.return (List.rev (commit :: acc)) +    in +    walk [] head_commit.hash n +end + +(* module Branch = struct *) +(*   type t = { hash : string; name : string } *) + +(*   let to_t (branch : Store.Reference.t) = *) +(*     { *) +(*       hash = Store.Reference.hash branch ; *) +(*       name = Store.Reference.contents branch; *) +(*     } *) + +(*   let of_id repo id = *) +(*     let* store = store repo in *) +(*     let hash = Store.Hash.of_hex id in *) +(*     Store.Ref.resolve store hash *) +(*     |> Lwt_result.map @@ function *) +(*     | Git.Reference.Ref branch -> to_t branch *) +(*        | _ -> failwith "no head tree id" *) + +(*   let all repo = *) +(*     let* store = store repo in *) +(*     let* refs = Store.Ref.list store in *) +(*     let branches = *) +(*       List.map *) +(*         (fun (reference, hash) -> *) +(*           let name = Git.Reference.to_string reference in *) +(*           let hash = Store.Hash.to_hex hash in *) +(*           { name; hash }) *) +(*         refs *) +(*     in *) +(*     Lwt_result.return branches *) +(* end *) + +module Entry = struct +  type t = { hash : string; name : string; perm : int } + +  let to_t (entry : Store.Value.Tree.entry) = +    let perm = +      match entry.perm with +      | `Commit -> 0o160000 +      | `Dir -> 0o040000 +      | `Everybody -> 0o100664 +      | `Exec -> 0o100755 +      | `Link -> 0o120000 +      | `Normal -> 0o100644 +    in +    let hash = Store.Hash.to_hex entry.node in +    { hash; name = entry.name; perm } +end + +module Tree = struct +  type t = { hash : string; entries : Entry.t list } + +  let to_t (tree : Store.Value.Tree.t) = +    let hash = Store.Value.Tree.hash tree |> Int.to_string in +    let entries = Store.Value.Tree.to_list tree |> List.map Entry.to_t in +    { hash; entries } + +  let of_id repo id = +    let* store = store repo in +    let hash = Store.Hash.of_hex id in +    Store.read store hash +    |> Lwt_result.map @@ function +       | Git.Value.Tree tree -> to_t tree +       | _ -> failwith "no head tree id" + +  let head repo : (t, Store.error) Lwt_result.t = +    let* store = store repo in +    let* hash = +      Store.Ref.resolve store Git.Reference.head +      |> Lwt_result.map Store.Hash.to_hex +    in +    of_id repo hash +end + +module Blob = struct +  type t = { content : string } + +  let to_t (blob : Store.Value.Blob.t) = +    { content = Store.Value.Blob.to_string blob } + +  let of_id repo id = +    let* store = store repo in +    let hash = Store.Hash.of_hex id in +    Store.read store hash +    |> Lwt_result.map @@ function +       | Git.Value.Blob blob -> to_t blob +       | _ -> failwith (id ^ " does not point to a blob object") +end diff --git a/lib/views.ml b/lib/views.ml index fc211c5..ca012fc 100644 --- a/lib/views.ml +++ b/lib/views.ml @@ -90,18 +90,19 @@ let root () =    respond @@ Page.render body_data  module Repo = struct -  open Resolvers +  let page_title repo = +    Printf.sprintf "%s — %s" repo (Resolvers.repo_description repo) -  let page_title repo = Printf.sprintf "%s — %s" repo (repo_description repo)    let li_of_author author = HTML.(li [] [ txt "%s" author ]) -  let li_of_branch repo (branch : branch) = -    HTML.(li [] [ Routes.link_to (Refs repo) (txt "%s" branch.name) ]) +  (* let li_of_branch repo (branch : Resolvers.Branch.t) = *) +  (*   HTML.(li [] [ Routes.link_to (Refs repo) (txt "%s" branch.name) ]) *) -  let li_of_commit repo commit = +  let li_of_commit repo (commit : Resolvers.Commit.t) =      let open HTML in +    let short_hash = Resolvers.short_hash commit.hash in      match commit.message with -    | None -> li [] [ txt "%s" commit.short_hash ] +    | None -> li [] [ txt "%s" short_hash ]      | Some msg ->          li []            [ @@ -109,12 +110,12 @@ module Repo = struct                (Commit (repo, commit.hash))                (null                   [ -                   span [ class_ "commit-hash" ] [ txt "%s" commit.short_hash ]; +                   span [ class_ "commit-hash" ] [ txt "%s" short_hash ];                     txt " — %s" msg;                   ]);            ] -  let li_of_entry repo entry = +  let li_of_entry repo (entry : Resolvers.Entry.t) =      let display_name =        if entry.perm = 0o040000 then entry.name ^ "/" else entry.name      in @@ -124,12 +125,12 @@ module Repo = struct      in      HTML.(li [] [ Routes.link_to route @@ txt "%s" display_name ]) -  let summary repo branches commits authors = +  let summary repo _branches commits authors =      let content =        HTML.          [            h3 [] [ txt "Branches" ]; -          ul [] (List.map (li_of_branch repo) branches); +          (* ul [] (List.map (li_of_branch repo) branches); *)            h3 [] [ txt "Latest commits" ];            ul [] (List.map (li_of_commit repo) commits);            h3 [] [ txt "Authors" ]; @@ -140,24 +141,24 @@ module Repo = struct      @@ Page.render ~page_title:(page_title repo)           {             title = repo; -           subtitle = repo_description repo; +           subtitle = Resolvers.repo_description repo;             topnav = Components.Topnav.(v ~active_path:Summary repo);             content;           } -  let refs repo branches = +  let refs repo _branches =      let content =        HTML.          [            h3 [] [ txt "Branches" ]; -          ul [] (List.map (li_of_branch repo) branches); +          (* ul [] (List.map (li_of_branch repo) branches); *)          ]      in      respond      @@ Page.render ~page_title:(page_title repo)           {             title = repo; -           subtitle = repo_description repo; +           subtitle = Resolvers.repo_description repo;             topnav = Components.Topnav.(v ~active_path:Refs repo);             content;           } @@ -174,30 +175,29 @@ module Repo = struct      @@ Page.render ~page_title:(page_title repo)           {             title = repo; -           subtitle = repo_description repo; +           subtitle = Resolvers.repo_description repo;             topnav = Components.Topnav.(v ~active_path:Log repo);             content;           } -  let files repo tree = -    let title = Printf.sprintf "%s" repo in +  let files repo (tree : Resolvers.Tree.t) =      let content =        HTML.          [ -          h3 [] [ txt "Files %s" tree.short_hash ]; +          h3 [] [ txt "Files %s" @@ Resolvers.short_hash tree.hash ];            ul [] (List.map (li_of_entry repo) tree.entries);          ]      in      respond      @@ Page.render ~page_title:(page_title repo)           { -           title; -           subtitle = repo_description repo; +           title = Printf.sprintf "%s" repo; +           subtitle = Resolvers.repo_description repo;             topnav = Components.Topnav.(v ~active_path:Files repo);             content;           } -  let file repo blob = +  let file repo (blob : Resolvers.Blob.t) =      let title = Printf.sprintf "%s" repo in      let to_numbered_line number line =        let n = number + 1 in @@ -218,20 +218,22 @@ module Repo = struct      @@ Page.render ~page_title:(page_title repo)           {             title; -           subtitle = repo_description repo; +           subtitle = Resolvers.repo_description repo;             topnav = Components.Topnav.(v ~active_path:Files repo);             content;           } -  let commit repo commit = +  let commit repo (commit : Resolvers.Commit.t) =      let message = match commit.message with Some msg -> msg | None -> "" in -    let title = Printf.sprintf "%s : %s" repo commit.short_hash in +    let title = +      Printf.sprintf "%s : %s" repo @@ Resolvers.short_hash commit.hash +    in      let content = HTML.[ h3 [] [ txt "%s" message ] ] in      respond      @@ Page.render ~page_title:(page_title repo)           {             title; -           subtitle = repo_description repo; +           subtitle = Resolvers.repo_description repo;             topnav = Components.Topnav.v repo;             content;           } | 
