diff --git a/c_src/geef.c b/c_src/geef.c index 7ce6865..e39e888 100644 --- a/c_src/geef.c +++ b/c_src/geef.c @@ -8,6 +8,7 @@ #include "blob.h" #include "library.h" #include "revwalk.h" +#include "index.h" #include "geef.h" #include #include @@ -18,6 +19,7 @@ ErlNifResourceType *geef_odb_type; ErlNifResourceType *geef_ref_type; ErlNifResourceType *geef_object_type; ErlNifResourceType *geef_revwalk_type; +ErlNifResourceType *geef_index_type; geef_atoms atoms; @@ -49,6 +51,9 @@ static int load(ErlNifEnv *env, void **priv, ERL_NIF_TERM load_info) geef_revwalk_type = enif_open_resource_type(env, NULL, "revwalk_type", geef_revwalk_free, ERL_NIF_RT_CREATE, NULL); + geef_index_type = enif_open_resource_type(env, NULL, + "index_type", geef_index_free, ERL_NIF_RT_CREATE, NULL); + if (geef_repository_type == NULL) return -1; @@ -138,6 +143,11 @@ static ErlNifFunc geef_funcs[] = {"revwalk_next", 1, geef_revwalk_next}, {"revwalk_sorting", 2, geef_revwalk_sorting}, {"revwalk_reset", 1, geef_revwalk_reset}, + {"index_new", 0, geef_revwalk_new}, + {"index_write", 1, geef_index_write}, + {"index_write_tree", 1, geef_index_write_tree}, + {"index_write_tree", 2, geef_index_write_tree}, + {"index_clear", 1, geef_index_clear}, }; ERL_NIF_INIT(geef_nif, geef_funcs, load, NULL, upgrade, unload) diff --git a/c_src/index.c b/c_src/index.c new file mode 100644 index 0000000..938309d --- /dev/null +++ b/c_src/index.c @@ -0,0 +1,87 @@ +#include "geef.h" +#include "oid.h" +#include "index.h" +#include +#include + +void geef_index_free(ErlNifEnv *env, void *cd) +{ + geef_index *index = (geef_index *) cd; + git_index_free(index->index); +} + +ERL_NIF_TERM +geef_index_new(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + geef_index *index; + ERL_NIF_TERM term; + + index = enif_alloc_resource(geef_index_type, sizeof(geef_index)); + if (!index) + return atoms.error; + + if (git_index_new(&index->index) < 0) + return geef_error(env); + + term = enif_make_resource(env, index); + enif_release_resource(index); + + return enif_make_tuple2(env, atoms.ok, term); +} + +ERL_NIF_TERM +geef_index_write(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + geef_index *index; + + if (!enif_get_resource(env, argv[0], geef_index_type, (void **) &index)) + return enif_make_badarg(env); + + if (git_index_write(index->index) < 0) + return geef_error(env); + + return atoms.ok; +} + +ERL_NIF_TERM +geef_index_write_tree(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + geef_index *index; + geef_repository *repo; + ErlNifBinary bin; + git_oid id; + int error; + + if (!enif_get_resource(env, argv[0], geef_index_type, (void **) &index)) + return enif_make_badarg(env); + + if (argc == 2) { + if (!enif_get_resource(env, argv[0], geef_repository_type, (void **) &repo)) + return enif_make_badarg(env); + + error = git_index_write_tree_to(&id, index->index, repo->repo); + } else { + error = git_index_write_tree(&id, index->index); + } + + if (error < 0) + return geef_error(env); + + if (geef_oid_bin(&bin, &id) < 0) + return atoms.error; + + return enif_make_tuple2(env, atoms.ok, enif_make_binary(env, &bin)); +} + +ERL_NIF_TERM +geef_index_clear(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + geef_index *index; + + if (!enif_get_resource(env, argv[0], geef_index_type, (void **) &index)) + return enif_make_badarg(env); + + git_index_clear(index->index); + + return atoms.ok; +} diff --git a/c_src/index.h b/c_src/index.h new file mode 100644 index 0000000..6102296 --- /dev/null +++ b/c_src/index.h @@ -0,0 +1,21 @@ +#ifndef GEEF_INDEX_H +#define GEEF_INDEX_H + +#include "erl_nif.h" +#include +#include "repository.h" + +extern ErlNifResourceType *geef_index_type; + +typedef struct { + git_index *index; +} geef_index; + +void geef_index_free(ErlNifEnv *env, void *cd); + +ERL_NIF_TERM geef_index_write(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM geef_index_write_tree(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM geef_index_clear(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); + + +#endif diff --git a/src/geef_index.erl b/src/geef_index.erl new file mode 100644 index 0000000..67cb89e --- /dev/null +++ b/src/geef_index.erl @@ -0,0 +1,109 @@ +%%%------------------------------------------------------------------- +%%% @author Carlos Martin Nieto +%%% @copyright (C) 2013, Carlos Martin Nieto +%%% @doc +%%% +%%% @end +%%% Created : 25 Apr 2013 by Carlos Martin Nieto +%%%------------------------------------------------------------------- +-module(geef_index). + +-behaviour(gen_server). + +%% API +-export([start_link/1]). +-export([new/0, write/1, write_tree/1, write_tree/2, clear/1, stop/1]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + +-record(state, {handle}). +-include("geef_records.hrl"). + +%%%=================================================================== +%%% API +%%%=================================================================== + +%% @doc Create a new index. This index is empty and not associated to +%% any repository. +-spec new() -> pid(). +new() -> + {ok, Handle} = geef_nif:index_new(), + start_link(Handle). + +%% @doc Write out the index file. This is only possible for indices +%% that are associated with a repository. +-spec write(pid()) -> ok | {error, term()}. +write(Pid) -> + gen_server:call(Pid, write). + +%% @doc Write out the index's contents to its the repository. +-spec write_tree(pid()) -> {ok, oid()} | {error, term()}. +write_tree(Pid) -> + gen_server:call(Pid, write_tree). + +%% @doc Write out the index's contents to the given repository +-spec write_tree(pid(), pid()) -> {ok, oid()} | {error, term()}. +write_tree(Pid, Repo) -> + gen_server:call(Pid, {write_tree, Repo}). + +%% @doc Clear the contents of the index. +-spec clear(pid()) -> ok. +clear(Pid) -> + gen_server:call(Pid, clear). + +-spec stop(pid()) -> ok. +stop(Pid) -> + gen_server:call(Pid, stop). + +%% @private +start_link(Handle) -> + gen_server:start_link(?MODULE, Handle, []). + +%%%=================================================================== +%%% gen_server callbacks +%%%=================================================================== + +%% @private +init(Handle) -> + {ok, #state{handle=Handle}}. + +%% @private +handle_call(write, _From, State = #state{handle=Handle}) -> + Reply = geef_nif:index_write(Handle), + {reply, Reply, State}; +handle_call(write_tree, _From, State = #state{handle=Handle}) -> + {ok, Oid} = geef_nif:index_write_tree(Handle), + Reply = #oid{oid=Oid}, + {reply, Reply, State}; +handle_call({write_tree, Repo}, _From, State = #state{handle=Handle}) -> + RepoHandle = geef_repo:handle(Repo), + {ok, Oid} = geef_nif:index_write_tree(Handle, RepoHandle), + Reply = #oid{oid=Oid}, + {reply, Reply, State}; +handle_call(clear, _From, State = #state{handle=Handle}) -> + Reply = geef_nif:index_clear(Handle), + {reply, Reply, State}; +handle_call(stop, _From, State) -> + {stop, normal, ok, State}. + +%% @private +handle_cast(_Msg, State) -> + {noreply, State}. + +%% @private +handle_info(_Info, State) -> + {noreply, State}. + +%% @private +terminate(_Reason, _State) -> + ok. + +%% @private +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%%%=================================================================== +%%% Internal functions +%%%=================================================================== diff --git a/src/geef_nif.erl b/src/geef_nif.erl index 9ca2d08..9121ea3 100644 --- a/src/geef_nif.erl +++ b/src/geef_nif.erl @@ -22,6 +22,9 @@ % revision walker -export([revwalk_new/1, revwalk_push/3, revwalk_next/1, revwalk_sorting/2, revwalk_reset/1]). +% index +-export([index_new/0, index_write/1, index_write_tree/1, index_write_tree/2, index_clear/1]). + -on_load(load_enif/0). -define(NIF_FN, nif_error(?LINE)). @@ -132,6 +135,21 @@ revwalk_sorting(_Walk, _Sort) -> revwalk_reset(_Walk) -> ?NIF_FN. +index_new() -> + ?NIF_FN. + +index_write(_Handle) -> + ?NIF_FN. + +index_write_tree(_Handle) -> + ?NIF_FN. + +index_write_tree(_Handle, _RepoHandle) -> + ?NIF_FN. + +index_clear(_Handle) -> + ?NIF_FN. + nif_error(Line) -> erlang:nif_error({nif_not_loaded,module,?MODULE,line,Line}). diff --git a/src/geef_object.erl b/src/geef_object.erl index 384e8f5..4530327 100644 --- a/src/geef_object.erl +++ b/src/geef_object.erl @@ -30,7 +30,7 @@ lookup(Repo, Id, Type) -> end. id(#object{handle=Handle}) -> - case geef:object_id(Handle) of + case geef_nif:object_id(Handle) of {ok, Oid} -> #oid{oid=Oid}; Other -> diff --git a/src/geef_repo.erl b/src/geef_repo.erl index 1b52c77..3df1ed5 100644 --- a/src/geef_repo.erl +++ b/src/geef_repo.erl @@ -16,7 +16,7 @@ %% API -export([open/1, init/2, path/1, workdir/1, odb/1, is_bare/1, references/1, discover/1, - lookup_object/2, lookup_reference/2, revwalk/1, stop/1]). + lookup_object/2, lookup_reference/2, revwalk/1, stop/1, handle/1]). -include("geef_records.hrl"). -record(state, {handle}). @@ -92,6 +92,11 @@ revwalk(Pid) -> stop(Pid) -> gen_server:call(Pid, stop). +%% @private +%% @doc Get the underlying repo resource6 +handle(Pid) -> + gen_server:call(Pid, handle). + %%%=================================================================== %%% gen_server callbacks %%%===================================================================