Allow creation of refs

This commit is contained in:
Carlos Martín Nieto
2013-05-02 06:24:15 +02:00
parent 9d7139d604
commit 0aa11d8532
7 changed files with 92 additions and 4 deletions

View File

@@ -128,6 +128,7 @@ static ErlNifFunc geef_funcs[] =
{"reference_resolve", 1, geef_reference_resolve},
{"reference_target", 1, geef_reference_target},
{"reference_type", 1, geef_reference_type},
{"reference_create", 5, geef_reference_create},
{"oid_fmt", 1, geef_oid_fmt},
{"oid_parse", 1, geef_oid_parse},
{"object_lookup", 2, geef_object_lookup},

View File

@@ -246,3 +246,58 @@ geef_reference_type(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
return term_type;
}
ERL_NIF_TERM
geef_reference_create(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
geef_repository *repo;
geef_ref *ref;
ErlNifBinary name, target;
ERL_NIF_TERM term_ref;
int error, force;
const char *pname, *ptarget;
if (!enif_get_resource(env, argv[0], geef_repository_type, (void **) &repo))
return enif_make_badarg(env);
if (!enif_inspect_iolist_as_binary(env, argv[1], &name))
return enif_make_badarg(env);
if (!enif_inspect_iolist_as_binary(env, argv[3], &target))
return enif_make_badarg(env);
/* Allocate the extra byte for the NUL terminator */
if (!enif_realloc_binary(&name, name.size + 1))
return atoms.error;
name.data[name.size-1] = '\0';
ref = enif_alloc_resource(geef_ref_type, sizeof(geef_ref));
force = enif_is_identical(argv[4], atoms.true);
pname = (const char *) name.data;
if (enif_is_identical(argv[2], atoms.oid)) {
const git_oid *oid = (const git_oid *) target.data;
error = git_reference_create(&ref->ref, repo->repo, pname, oid, force);
} else if (enif_is_identical(argv[2], atoms.symbolic)) {
/* Allocate the extra byte for the NUL terminator */
if (!enif_realloc_binary(&target, target.size + 1))
return atoms.error;
target.data[target.size - 1] = '\0';
ptarget = (const char *) target.data;
error = git_reference_symbolic_create(&ref->ref, repo->repo, pname, ptarget, force);
} else {
return enif_make_badarg(env);
}
if (error < 0)
return geef_error(env);
term_ref = enif_make_resource(env, ref);
enif_release_resource(ref);
return enif_make_tuple2(env, atoms.ok, term_ref);
}

View File

@@ -17,6 +17,7 @@ ERL_NIF_TERM geef_reference_lookup(ErlNifEnv *env, int argc, const ERL_NIF_TERM
ERL_NIF_TERM geef_reference_resolve(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM geef_reference_target(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM geef_reference_type(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM geef_reference_create(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
void geef_ref_free(ErlNifEnv *env, void *cd);

View File

@@ -2,7 +2,7 @@
%%% NIF functions, not to be used directly.
-module(geef_nif).
-export([reference_list/1,
-export([reference_list/1, reference_create/5,
reference_to_id/2, reference_glob/2, reference_lookup/2, reference_resolve/1,
reference_target/1, reference_type/1, odb_object_exists/2, odb_write/3]).
@@ -60,6 +60,9 @@ repository_discover(_Path) ->
reference_list(_Repo) ->
nif_error(?LINE).
reference_create(_Repo, _Refname, _Type, _Target, _Force) ->
?NIF_FN.
reference_to_id(_Repo, _Refname) ->
nif_error(?LINE).

View File

@@ -1,6 +1,6 @@
-module(geef_ref).
-export([lookup/2, resolve/1, target/1, name_to_id/2]).
-export([lookup/2, resolve/1, target/1, name_to_id/2, create/4]).
-include("geef_records.hrl").
@@ -16,6 +16,12 @@ new(Handle) ->
end,
#ref{handle=Handle, type=Type, target=Target}.
-spec create(pid(), iolist(), oid() | binary(), boolean()) -> {ok, ref()} | {error, term()}
.
create(Repo, Refname, Target, Force) ->
{ok, Ref} = geef_repo:create_reference(Repo, Refname, Target, Force),
{ok, new(Ref)}.
-spec lookup(pid(), iolist()) -> {ok, ref()} | {error, term()}.
lookup(Repo, Refname) ->
case geef_repo:lookup_reference(Repo, Refname) of

View File

@@ -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, handle/1]).
lookup_object/2, lookup_reference/2, create_reference/4, revwalk/1, stop/1, handle/1]).
-include("geef_records.hrl").
-record(state, {handle}).
@@ -85,6 +85,10 @@ lookup_object(Pid, Oid) ->
lookup_reference(Pid, Name) ->
gen_server:call(Pid, {lookup_reference, Name}).
%% @private
create_reference(Pid, Name, Target, Force) ->
gen_server:call(Pid, {create_reference, Name, Target, Force}).
%% @doc Create a revision walker for the given repository.
revwalk(Pid) ->
gen_server:call(Pid, revwalk).
@@ -127,6 +131,9 @@ handle_call({lookup_object, Oid}, _From, State = #state{handle=Handle}) ->
handle_call({lookup_reference, Name}, _From, State = #state{handle=Handle}) ->
Reply = geef_nif:reference_lookup(Handle, Name),
{reply, Reply, State};
handle_call({create_reference, Name, Target, Force}, _From, State = #state{handle=Handle}) ->
Reply = handle_create_reference(Handle, Name, Target, Force),
{reply, Reply, State};
handle_call(stop, _From, State) ->
{stop, normal, ok, State};
handle_call(revwalk, _From, State = #state{handle=Handle}) ->
@@ -182,3 +189,8 @@ handle_revwalk(Handle) ->
Error ->
Error
end.
handle_create_reference(Repo, Refname, #oid{oid=Oid}, Force) ->
geef_nif:reference_create(Repo, Refname, oid, Oid, Force);
handle_create_reference(Repo, Refname, Target, Force) ->
geef_nif:reference_create(Repo, Refname, symbolic, Target, Force).

View File

@@ -3,7 +3,7 @@
-include_lib("eunit/include/eunit.hrl").
repo_test_() ->
{foreach, fun start/0, fun stop/1, [fun bare_test/1, fun odb_write_test/1]}.
{foreach, fun start/0, fun stop/1, [fun bare_test/1, fun odb_write_test/1, fun create_ref_test/1]}.
start() ->
{A, B, C} = now(),
@@ -22,5 +22,15 @@ odb_write_test(Repo) ->
Expected = geef_oid:parse("c300118399f01fe52b316061b5d32beb27e0adfd"),
[?_assertEqual(Actual, Expected)].
create_ref_test(Repo) ->
odb_write_test(Repo),
Id = geef_oid:parse("c300118399f01fe52b316061b5d32beb27e0adfd"),
{ok, _} = geef_ref:create(Repo, "refs/heads/branch", Id, true),
{ok, _} = geef_ref:create(Repo, "refs/heads/other", "refs/heads/branch", true),
{ok, Ref0} = geef_ref:lookup(Repo, "refs/heads/branch"),
{ok, Ref1} = geef_ref:lookup(Repo, "refs/heads/other"),
[?_assertEqual(geef_ref:target(Ref0), Id),
?_assertEqual(geef_ref:target(Ref1), <<"refs/heads/branch">>)].
stop(Repo) ->
geef_repo:stop(Repo).