summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius Peter <marius.peter@tutanota.com>2025-06-21 12:09:35 +0200
committerMarius Peter <marius.peter@tutanota.com>2025-06-21 12:09:35 +0200
commit034ae69f2f22d7957386e73b3c42053fbf0cdfb2 (patch)
treeb991f59a492b62b059029aa7365547e826c07416
parent6e07594aace8bc2c6f99219b4022a68291201aad (diff)
Refactor resolvers.
-rw-r--r--lib/handlers.ml19
-rw-r--r--lib/resolvers.ml258
-rw-r--r--lib/views.ml52
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;
}
Copyright 2019--2025 Marius PETER