diff --git a/c_src/geef.c b/c_src/geef.c index d04ee13..b54fb66 100644 --- a/c_src/geef.c +++ b/c_src/geef.c @@ -179,6 +179,9 @@ static ErlNifFunc geef_funcs[] = {"index_write_tree", 1, geef_index_write_tree}, {"index_write_tree", 2, geef_index_write_tree}, {"index_add", 2, geef_index_add}, + {"index_count", 1, geef_index_count}, + {"index_get", 3, geef_index_get}, + {"index_nth", 2, geef_index_nth}, {"index_clear", 1, geef_index_clear}, {"index_read_tree", 2, geef_index_read_tree}, {"signature_new", 2, geef_signature_new}, diff --git a/c_src/index.c b/c_src/index.c index 75c5e0b..2c7264f 100644 --- a/c_src/index.c +++ b/c_src/index.c @@ -138,6 +138,89 @@ geef_index_add(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return atoms.ok; } +ERL_NIF_TERM +geef_index_count(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); + + return enif_make_uint(env, git_index_entrycount(index->index)); +} + +ERL_NIF_TERM entry_to_term(ErlNifEnv *env, const git_index_entry *entry) +{ + ErlNifBinary id, path; + ERL_NIF_TERM mode; + size_t len; + + if (geef_oid_bin(&id, &entry->oid) < 0) + return geef_oom(env); + + len = strlen(entry->path); + if (!enif_alloc_binary(len, &path)) { + enif_release_binary(&id); + return geef_oom(env); + } + memcpy(path.data, entry->path, len); + + mode = enif_make_uint(env, entry->mode); + + return enif_make_tuple4(env, atoms.ok, enif_make_binary(env, &path), enif_make_binary(env, &id), + mode); +} + +ERL_NIF_TERM +geef_index_nth(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + size_t nth; + geef_index *index; + const git_index_entry *entry; + + if (!enif_get_resource(env, argv[0], geef_index_type, (void **) &index)) + return enif_make_badarg(env); + + if (!enif_get_ulong(env, argv[1], &nth)) + return enif_make_badarg(env); + + entry = git_index_get_byindex(index->index, nth); + if (entry == NULL) + return geef_error(env); + + return entry_to_term(env, entry); +} + +ERL_NIF_TERM +geef_index_get(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + unsigned int stage; + ErlNifBinary path; + geef_index *index; + const git_index_entry *entry; + + if (!enif_get_resource(env, argv[0], geef_index_type, (void **) &index)) + return enif_make_badarg(env); + + if (!enif_get_uint(env, argv[2], &stage)) + return enif_make_badarg(env); + + if (!enif_inspect_iolist_as_binary(env, argv[1], &path)) + return enif_make_badarg(env); + + if (geef_terminate_binary(&path) < 0) { + enif_release_binary(&path); + return geef_oom(env); + } + + entry = git_index_get_bypath(index->index, (char *) path.data, stage); + enif_release_binary(&path); + if (entry == NULL) + return geef_error(env); + + return entry_to_term(env, entry); +} + ERL_NIF_TERM geef_index_clear(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { diff --git a/c_src/index.h b/c_src/index.h index 6bd8981..35871ae 100644 --- a/c_src/index.h +++ b/c_src/index.h @@ -19,6 +19,8 @@ ERL_NIF_TERM geef_index_write_tree(ErlNifEnv *env, int argc, const ERL_NIF_TERM ERL_NIF_TERM geef_index_clear(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); ERL_NIF_TERM geef_index_read_tree(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); ERL_NIF_TERM geef_index_add(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); -ERL_NIF_TERM geef_index_new(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM geef_index_count(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM geef_index_nth(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM geef_index_get(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); #endif diff --git a/src/geef_index.erl b/src/geef_index.erl index 114f485..cdee3a9 100644 --- a/src/geef_index.erl +++ b/src/geef_index.erl @@ -12,7 +12,7 @@ %% API -export([start_link/1]). --export([new/0, write/1, write_tree/1, write_tree/2, clear/1, stop/1, read_tree/2, add/2]). +-export([new/0, write/1, write_tree/1, write_tree/2, clear/1, stop/1, read_tree/2, add/2, count/1, get/3, nth/2]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, @@ -59,6 +59,27 @@ read_tree(Pid, #geef_object{type=tree, handle=TreeHandle}) -> add(Pid, Entry) -> gen_server:call(Pid, {add, Entry}). +-spec count(pid()) -> non_neg_integer(). +count(Pid) -> + gen_server:call(Pid, count). + +%% @doc Retrieve an entry with a particular path and stage. +-spec get(pid(), iolist(), non_neg_integer()) -> {ok, entry()} | {error, term()}. +get(Pid, Path, Stage) -> + maybe_entry(gen_server:call(Pid, {get, Path, Stage})). + +%% @doc Retrieve an entry by index. Different stages of a path are +%% considered different entries. +-spec nth(pid(), non_neg_integer()) -> {ok, entry()} | {error, term()}. +nth(Pid, Nth) -> + maybe_entry(gen_server:call(Pid, {nth, Nth})). + +maybe_entry({ok, Path, Id, Mode}) -> + {ok, #geef_index_entry{path=Path, id=#geef_oid{oid=Id}, mode=Mode}}; +maybe_entry(Error = {error, _}) -> + Error. + + %% @doc Clear the contents of the index. -spec clear(pid()) -> ok. clear(Pid) -> @@ -102,6 +123,19 @@ handle_call(stop, _From, State) -> handle_call({read_tree, TreeHandle}, _From, State = #state{handle=Handle}) -> Reply = geef_nif:index_read_tree(Handle, TreeHandle), {reply, Reply, State}; + +handle_call(count, _From, State = #state{handle=Handle}) -> + Reply = geef_nif:index_count(Handle), + {reply, Reply, State}; + +handle_call({nth, Nth}, _From, State = #state{handle=Handle}) -> + Reply = geef_nif:index_nth(Handle, Nth), + {reply, Reply, State}; + +handle_call({get, Path, Stage}, _From, State = #state{handle=Handle}) -> + Reply = geef_nif:index_get(Handle, Path, Stage), + {reply, Reply, State}; + handle_call({add, Entry}, _From, State = #state{handle=Handle}) -> Reply = geef_nif:index_add(Handle, Entry), {reply, Reply, State}. diff --git a/src/geef_nif.erl b/src/geef_nif.erl index d1d9e1f..f0357d7 100644 --- a/src/geef_nif.erl +++ b/src/geef_nif.erl @@ -154,6 +154,18 @@ index_write_tree(_Handle, _RepoHandle) -> index_read_tree(_Handle, _TreeHandle) -> ?NIF_FN. +-spec index_count(term()) -> non_neg_integer(). +index_count(_Handle) -> + ?NIF_FN. + +-spec index_nth(term(), non_neg_integer()) -> {ok, geef_index:entry()} | {error, term()}. +index_nth(_Handle, _Nth) -> + ?NIF_FN. + +-spec index_get(term(), iolist(), non_neg_integer()) -> {ok, geef_index:entry()} | {error, term()}. +index_get(_Handle, _Path, _Stage) -> + ?NIF_FN. + index_add(_Handle, _Entry) -> ?NIF_FN. diff --git a/test/repo_test.erl b/test/repo_test.erl index 5995683..28213f0 100644 --- a/test/repo_test.erl +++ b/test/repo_test.erl @@ -34,7 +34,10 @@ index_add_test(Repo) -> ok = geef_index:add(Idx, Entry), {ok, TreeId} = geef_index:write_tree(Idx, Repo), Expected = geef_oid:parse("5a20bbbf65ea75ad4d9f995d179156824ccca3a1"), - [?_assertEqual(Expected, TreeId)]. + {ok, Entry1} = geef_index:get(Idx, "README", 0), + [?_assertEqual(Expected, TreeId), + ?_assertEqual(BlobId, Entry1#geef_index_entry.id), + ?_assertEqual(geef_index:count(Idx), 1)]. ref_test(Repo) -> odb_write_test(Repo),