diff --git a/c_src/geef.c b/c_src/geef.c index b54fb66..881a0a1 100644 --- a/c_src/geef.c +++ b/c_src/geef.c @@ -184,8 +184,7 @@ static ErlNifFunc geef_funcs[] = {"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}, - {"signature_new", 3, geef_signature_new}, + {"signature_default", 1, geef_signature_default}, }; ERL_NIF_INIT(geef_nif, geef_funcs, load, NULL, upgrade, unload) diff --git a/c_src/signature.c b/c_src/signature.c index b93fb85..2ce8863 100644 --- a/c_src/signature.c +++ b/c_src/signature.c @@ -1,7 +1,53 @@ #include "geef.h" +#include "repository.h" #include #include +static int geef_string_to_bin(ErlNifBinary *bin, const char *str) +{ + size_t len; + + len = strlen(str); + if (!enif_alloc_binary(len, bin)) + return -1; + + memcpy(bin->data, str, len); + return 0; +} + +ERL_NIF_TERM +geef_signature_default(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + git_signature *sig; + geef_repository *repo; + ErlNifBinary name, email; + + if (!enif_get_resource(env, argv[0], geef_repository_type, (void **) &repo)) + return enif_make_badarg(env); + + memset(&name, 0, sizeof(ErlNifBinary)); + memset(&email, 0, sizeof(ErlNifBinary)); + + if (git_signature_default(&sig, repo->repo) < 0) + return geef_error(env); + + if (geef_string_to_bin(&name, sig->name) < 0) + goto oom; + + if (geef_string_to_bin(&email, sig->email) < 0) + goto oom; + + return enif_make_tuple5(env, atoms.ok, + enif_make_binary(env, &name), enif_make_binary(env, &email), + enif_make_ulong(env, sig->when.time), enif_make_uint(env, sig->when.offset)); +oom: + git_signature_free(sig); + enif_release_binary(&name); + enif_release_binary(&email); + + return geef_oom(env); +} + ERL_NIF_TERM geef_signature_new(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { diff --git a/c_src/signature.h b/c_src/signature.h index 0fbaafa..2c63971 100644 --- a/c_src/signature.h +++ b/c_src/signature.h @@ -1,3 +1,4 @@ #include "geef.h" ERL_NIF_TERM geef_signature_new(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM geef_signature_default(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); diff --git a/lib/geef/signature.ex b/lib/geef/signature.ex index 0f9eb74..58722b2 100644 --- a/lib/geef/signature.ex +++ b/lib/geef/signature.ex @@ -1,9 +1,12 @@ defrecord Geef.Signature, Record.extract(:geef_signature, from: "src/geef_records.hrl") do - def new(name, email), do: :geef_sig.new(name, email) |> maybe_sig - def new(name, email, time), do: :geef_sig.new(name, email, time) |> maybe_sig + def now(name, email), do: :geef_sig.now(name, email) |> from_erl - defp maybe_sig({:ok, sig}), do: Geef.Signature.new(sig) - defp maybe_sig({:error, error}), do: raise error + def default(repo), do: :geef_sig.default(repo) |> maybe_sig + + defp maybe_sig({:ok, sig}), do: from_erl(sig) + defp maybe_sig(error = {:error, _}), do: error + + defp from_erl(sig), do: set_elem(sig, 0, Geef.Signature) end diff --git a/src/geef_nif.erl b/src/geef_nif.erl index a87ad81..6c416aa 100644 --- a/src/geef_nif.erl +++ b/src/geef_nif.erl @@ -172,6 +172,10 @@ index_add(_Handle, _Entry) -> index_clear(_Handle) -> ?NIF_FN. +-spec signature_default(term()) -> {ok, geef_sig:signature()} | {error, term()}. +signature_default(_Repo) -> + ?NIF_FN. + signature_new(_Name, _Email) -> ?NIF_FN. diff --git a/src/geef_sig.erl b/src/geef_sig.erl index afb7d70..22a49f0 100644 --- a/src/geef_sig.erl +++ b/src/geef_sig.erl @@ -6,23 +6,29 @@ -type signature() :: #geef_signature{}. -export_type([time/0, signature/0]). --export([new/2, new/3]). +-export([default/1, now/2]). --spec new(iolist(), iolist()) -> {ok, signature()} | {error, term()}. -new(Name0, Email0) -> - case geef_nif:signature_new(Name0, Email0) of - {ok, Name, Email, Time0, Offset} -> - Time = {{Time0 div 1000000, Time0 rem 1000000, 0}, Offset}, - {ok, #geef_signature{name=Name, email=Email, time=Time}}; - Err -> +%% @doc Create a signature for the repository's configured username and +%% email, with a timestamp of now. +-spec default(pid()) -> {ok, signature()} | {error, term()}. +default(Repo) -> + RepoHandle = geef_repo:handle(Repo), + case geef_nif:signature_default(RepoHandle) of + {ok, Name, Email, Timestamp, Offset} -> + Time = {{Timestamp div 1000000, Timestamp rem 1000000, 0}, Offset}, + Sig = #geef_signature{name=Name, email=Email, time=Time}, + {ok, Sig}; + Err = {error, _} -> Err end. --spec new(iolist(), iolist(), time()) -> {ok, signature()} | {error, term()}. -new(Name0, Email0, Time) -> - case geef_nif:signature_new(Name0, Email0, 0) of - {ok, Name, Email} -> - {ok, #geef_signature{name=Name, email=Email, time=Time}}; - Err -> - Err - end. +%% @doc Create a signature with the specified username and email, with +%% a timestamp of now +now(Name, Email) -> + Now = now(), + %% We ask two questions "what's the time here?" and "what's the + %% time in UTC-Land?". The difference in minutes is our offset. + Local = calendar:datetime_to_gregorian_seconds(calendar:now_to_local_time(Now)), + UTC = calendar:datetime_to_gregorian_seconds(calendar:now_to_universal_time(Now)), + Offset = (Local - UTC) div 60, + #geef_signature{name=Name, email=Email, time={Now, Offset}}.