Repositories / ocaml-git.git
ocaml-git.git
Clone (read-only): git clone http://git.guha-anderson.com/git/ocaml-git.git
@@ -109,6 +109,8 @@ external raw_tree_entry : repo_handle -> string -> string -> tree_entry_raw = "k external raw_tree : repo_handle -> string -> string -> tree_entry_raw list = "kg_tree" external raw_blob : repo_handle -> string -> string = "kg_blob" external raw_commits : repo_handle -> string -> int -> commit_raw list = "kg_commits" +external raw_commit_lookup : repo_handle -> string -> commit_raw = "kg_commit_lookup" +external raw_commit_diff : repo_handle -> string -> string = "kg_commit_diff" external raw_status : repo_handle -> status_raw list = "kg_status" external raw_index : repo_handle -> index_handle = "kg_index" external raw_index_size : index_handle -> int = "kg_index_size" @@ -243,6 +245,14 @@ let commits ?(limit : int = 50) (repo : t) (branch : string) : commit list = require_open repo; raw_commits repo.handle branch limit |> List.map commit_of_raw +let commit_lookup (repo : t) (id : oid) : commit = + require_open repo; + raw_commit_lookup repo.handle id |> commit_of_raw + +let commit_diff (repo : t) (id : oid) : string = + require_open repo; + raw_commit_diff repo.handle id + let index (repo : t) : index = require_open repo; { repo; handle = raw_index repo.handle; index_closed = false }
@@ -89,6 +89,8 @@ val tree_entry : ?commit:commit -> t -> string -> tree_entry val tree : ?commit:commit -> ?path:string -> t -> unit -> tree_listing val blob : ?commit:commit -> t -> string -> blob val commits : ?limit:int -> t -> string -> commit list +val commit_lookup : t -> oid -> commit +val commit_diff : t -> oid -> string val index : t -> index val index_size : index -> int
@@ -400,6 +400,54 @@ CAMLprim value kg_blob(value repo_v, value oid_v) { CAMLreturn(result); } +CAMLprim value kg_commit_lookup(value repo_v, value oid_v) { + CAMLparam2(repo_v, oid_v); + CAMLlocal1(result); + git_oid oid; + git_commit *commit = NULL; + oid_from_string(&oid, oid_v); + check(git_commit_lookup(&commit, repo_val(repo_v), &oid), "git_commit_lookup"); + result = copy_commit(commit); + git_commit_free(commit); + CAMLreturn(result); +} + +/* Unified-diff text for a commit against its first parent (or the empty tree + for a root commit). Mirrors `git show --format= <id>` output. */ +CAMLprim value kg_commit_diff(value repo_v, value oid_v) { + CAMLparam2(repo_v, oid_v); + CAMLlocal1(result); + git_repository *repo = repo_val(repo_v); + git_oid oid; + git_commit *commit = NULL; + git_commit *parent = NULL; + git_tree *new_tree = NULL; + git_tree *old_tree = NULL; + git_diff *diff = NULL; + git_diff_options opts; + git_buf buf = GIT_BUF_INIT; + + oid_from_string(&oid, oid_v); + check(git_commit_lookup(&commit, repo, &oid), "git_commit_lookup"); + check(git_commit_tree(&new_tree, commit), "git_commit_tree"); + if (git_commit_parentcount(commit) > 0) { + check(git_commit_parent(&parent, commit, 0), "git_commit_parent"); + check(git_commit_tree(&old_tree, parent), "git_commit_tree"); + } + check(git_diff_options_init(&opts, GIT_DIFF_OPTIONS_VERSION), "git_diff_options_init"); + check(git_diff_tree_to_tree(&diff, repo, old_tree, new_tree, &opts), "git_diff_tree_to_tree"); + check(git_diff_to_buf(&buf, diff, GIT_DIFF_FORMAT_PATCH), "git_diff_to_buf"); + + result = caml_copy_string(buf.ptr ? buf.ptr : ""); + git_buf_dispose(&buf); + git_diff_free(diff); + if (old_tree) git_tree_free(old_tree); + git_tree_free(new_tree); + if (parent) git_commit_free(parent); + git_commit_free(commit); + CAMLreturn(result); +} + CAMLprim value kg_commits(value repo_v, value branch_name_v, value limit_v) { CAMLparam3(repo_v, branch_name_v, limit_v); CAMLlocal3(list, commit_v, result);