diff --git a/c_src/geef.c b/c_src/geef.c index 8a1dea5..3d820f0 100644 --- a/c_src/geef.c +++ b/c_src/geef.c @@ -154,6 +154,7 @@ static ErlNifFunc geef_funcs[] = {"reference_type", 1, geef_reference_type}, {"reference_name", 1, geef_reference_name}, {"reference_create", 5, geef_reference_create}, + {"reference_dwim", 2, geef_reference_dwim}, {"oid_fmt", 1, geef_oid_fmt}, {"oid_parse", 1, geef_oid_parse}, {"object_lookup", 2, geef_object_lookup}, diff --git a/c_src/reference.c b/c_src/reference.c index 7f09e64..14a69d5 100644 --- a/c_src/reference.c +++ b/c_src/reference.c @@ -94,6 +94,35 @@ geef_reference_resolve(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) return enif_make_tuple2(env, atoms.ok, term_ref); } +ERL_NIF_TERM +geef_reference_dwim(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + ErlNifBinary bin; + geef_ref *ref; + ERL_NIF_TERM term_ref; + geef_repository *repo; + + 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], &bin)) + return enif_make_badarg(env); + + if (!geef_terminate_binary(&bin)) + return geef_oom(env); + + ref = enif_alloc_resource(geef_ref_type, sizeof(geef_ref)); + if (git_reference_dwim(&ref->ref, repo->repo, (char *)bin.data) < 0) { + enif_release_binary(&bin); + return geef_error(env); + } + + term_ref = enif_make_resource(env, ref); + enif_release_resource(ref); + + return enif_make_tuple2(env, atoms.ok, term_ref); +} + void geef_ref_free(ErlNifEnv *env, void *cd) { geef_ref *ref = (geef_ref *) cd; diff --git a/c_src/reference.h b/c_src/reference.h index 51594a2..76bd161 100644 --- a/c_src/reference.h +++ b/c_src/reference.h @@ -19,6 +19,7 @@ ERL_NIF_TERM geef_reference_target(ErlNifEnv *env, int argc, const ERL_NIF_TERM ERL_NIF_TERM geef_reference_type(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); ERL_NIF_TERM geef_reference_name(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); ERL_NIF_TERM geef_reference_create(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM geef_reference_dwim(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); void geef_ref_free(ErlNifEnv *env, void *cd); diff --git a/lib/geef/reference.ex b/lib/geef/reference.ex index 521ebb2..ba254d9 100644 --- a/lib/geef/reference.ex +++ b/lib/geef/reference.ex @@ -37,4 +37,20 @@ defrecord Geef.Reference, Record.extract(:geef_reference, from: "src/geef_record end end + def dwim(repo, name) do + case :geef_ref.dwim(repo, name) do + {:ok, ref} -> + {:ok, Geef.Reference.new ref} + error -> + error + end + end + + def dwim!(repo, name) do + case dwim(repo, name) do + {:ok, ref} -> ref + {:error, err} -> raise err + end + end + end diff --git a/src/geef_nif.erl b/src/geef_nif.erl index dba27bc..da26314 100644 --- a/src/geef_nif.erl +++ b/src/geef_nif.erl @@ -62,6 +62,9 @@ reference_type(_Handle) -> reference_name(_Handle) -> nif_error(?LINE). +reference_dwim(_Handle, _Name) -> + ?NIF_FN. + odb_object_exists(_Val, _Val) -> nif_error(?LINE). diff --git a/src/geef_ref.erl b/src/geef_ref.erl index a129ac3..ef52580 100644 --- a/src/geef_ref.erl +++ b/src/geef_ref.erl @@ -1,6 +1,6 @@ -module(geef_ref). --export([lookup/2, resolve/1, create/4]). +-export([lookup/2, resolve/1, create/4, dwim/2]). -include("geef_records.hrl"). @@ -42,3 +42,13 @@ resolve(#geef_reference{handle=Handle}) -> Other -> Other end. + +-spec dwim(pid(), iolist()) -> {ok, geef_reference()} | {error, term()}. +dwim(Repo, Name) -> + case geef_repo:reference_dwim(Repo, Name) of + {ok, Handle} -> + {ok, FullName} = geef_nif:reference_name(Handle), + {ok, new(FullName, Handle)}; + Err -> + Err + end. diff --git a/src/geef_repo.erl b/src/geef_repo.erl index 817d072..1050ecb 100644 --- a/src/geef_repo.erl +++ b/src/geef_repo.erl @@ -16,7 +16,8 @@ %% 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, create_reference/4, revwalk/1, stop/1, handle/1]). + lookup_object/2, lookup_reference/2, create_reference/4, revwalk/1, stop/1, + reference_dwim/2, handle/1]). -include("geef_records.hrl"). -record(state, {handle}). @@ -85,6 +86,10 @@ lookup_object(Pid, Oid) -> lookup_reference(Pid, Name) -> gen_server:call(Pid, {lookup_reference, Name}). +%% @private +reference_dwim(Pid, Name) -> + gen_server:call(Pid, {dwim_reference, Name}). + %% @private create_reference(Pid, Name, Target, Force) -> gen_server:call(Pid, {create_reference, Name, Target, Force}). @@ -131,6 +136,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({dwim_reference, Name}, _From, State = #state{handle=Handle}) -> + Reply = geef_nif:reference_dwim(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}; diff --git a/test/repo_test.erl b/test/repo_test.erl index 711b39b..64b2dfc 100644 --- a/test/repo_test.erl +++ b/test/repo_test.erl @@ -5,7 +5,8 @@ repo_test_() -> {foreach, fun start/0, fun stop/1, [fun bare_test/1, fun odb_write_test/1, - fun create_ref_test/1, fun index_add_test/1]}. + fun create_ref_test/1, fun index_add_test/1, + fun dwim_ref_test/1]}. start() -> {A, B, C} = now(), @@ -45,6 +46,15 @@ create_ref_test(Repo) -> [?_assertEqual(Ref0#geef_reference.target, Id), ?_assertEqual(Ref1#geef_reference.target, <<"refs/heads/branch">>)]. +dwim_ref_test(Repo) -> + odb_write_test(Repo), + Id = geef_oid:parse("c300118399f01fe52b316061b5d32beb27e0adfd"), + {ok, _} = geef_ref:create(Repo, "refs/heads/branch", Id, true), + {ok, Branch} = geef_ref:dwim(Repo, "branch"), + Actual = Branch#geef_reference.name, + Expected = <<"refs/heads/branch">>, + [?_assertEqual(Actual, Expected)]. + rm_r(Path) -> case filelib:is_dir(Path) of false ->