diff options
-rw-r--r-- | lib/git_helpers.ml | 72 |
1 files changed, 50 insertions, 22 deletions
diff --git a/lib/git_helpers.ml b/lib/git_helpers.ml index 07b0d04..5e5d4cd 100644 --- a/lib/git_helpers.ml +++ b/lib/git_helpers.ml @@ -1,33 +1,61 @@ -type commit_info = { +open Lwt.Infix +module Store = Git_unix.Store +module Value = Git.Value + +type user_record = { name : string; email : string } + +type commit_record = { hash : string; + parents : string list; + author : Git.User.t; message : string option; - author : string; - date : string; } let full_path path = Filename.concat Config.git_directory path let store repo_path = let path = Fpath.v @@ full_path repo_path in - Git_unix.Store.v ~dotgit:path path + Store.v ~dotgit:path path + +let short_hash hash = String.sub hash 0 8 + +let repo_description repo_path = + let description_path = Filename.concat (full_path repo_path) "description" in + In_channel.with_open_text description_path In_channel.input_all -let latest_commits repo_path ~count = +(* Read a Git object and turn it into our [commit_record], or propagate an error. *) +let get_commit_record store h = + Store.read store h >>= function + | Ok (Value.Commit c) -> + Lwt.return_ok + { + hash = Store.Hash.to_hex h; + parents = Store.Value.Commit.parents c |> List.map Store.Hash.to_hex; + author = Store.Value.Commit.author c; + message = Store.Value.Commit.message c; + } + | Ok _ -> Lwt.return_error (`Msg "object is not a commit") + | Error e -> Lwt.return_error e + +let recent_commits repo_path n = let open Lwt_result.Syntax in - let* store_result = store repo_path in - let* commits = Git.Commit.Make in - commits - -let all_branches repo_path = - let cmd = - Printf.sprintf "git -C %s branch --format=%%(refname:short)" - @@ full_path repo_path + let* store = store repo_path in + let* head = Store.Ref.resolve store Git.Reference.head in + let rec walk acc hash count = + if count = 0 then Lwt.return_ok (List.rev acc) + else + get_commit_record store hash >>= function + | Error e -> Lwt.return_error e + | Ok commit -> ( + match commit.parents with + | parent :: _ -> + walk (commit :: acc) (Store.Hash.of_hex parent) (count - 1) + | [] -> Lwt.return_ok (List.rev (commit :: acc))) in - Lwt.catch - (fun () -> - let%lwt output = Lwt_process.pread ("", [| "sh"; "-c"; cmd |]) in - let branches = - String.split_on_char '\n' output - |> List.filter (fun s -> String.trim s <> "") - in - Lwt.return_ok branches) - (fun exn -> Lwt.return_error (Printexc.to_string exn)) + walk [] head n + +let get_commit repo_path id = + let open Lwt_result.Syntax in + let* store = store repo_path in + let id = Store.Hash.of_hex id in + get_commit_record store id |