Files
geef/c_src/signature.c
Carlos Martín Nieto 22ab293910 Basic reflog support
For now it simply includes reading in the reflog as a list of
entries. This does mean that the drop/append functions don't need to be
wrapped, as we can use erlang's list handling.

It however also means that we cannot write this back out, as there is
currently no way to create an empty reflog that we can fill with our own
list.
2014-02-13 17:41:11 +01:00

202 lines
4.5 KiB
C

#include "geef.h"
#include "repository.h"
#include <string.h>
#include <git2.h>
int geef_signature_from_erl(git_signature **out, ErlNifEnv *env, ERL_NIF_TERM *err, ERL_NIF_TERM term)
{
const ERL_NIF_TERM *time_tuple, *time, *tuple;
ErlNifBinary name, email;
git_signature *sig;
git_time_t gtime;
int offset, arity;
unsigned int secs, megasecs;
memset(&name, 0, sizeof(ErlNifBinary));
memset(&email, 0, sizeof(ErlNifBinary));
if (!enif_get_tuple(env, term, &arity, &tuple))
goto on_badarg;
if (arity != 4)
goto on_badarg;
if (!enif_inspect_iolist_as_binary(env, tuple[1], &name))
goto on_badarg;
if (!enif_inspect_iolist_as_binary(env, tuple[2], &email))
goto on_badarg;
if (!geef_terminate_binary(&name))
goto on_oom;
if (!geef_terminate_binary(&email))
goto on_oom;
/*
* Now that we have the name and e-mail, we need to extract
* the time tuple. This is quite annoying as the time is yet
* another tuple.
*/
if (!enif_get_tuple(env, tuple[3], &arity, &time_tuple))
goto on_badarg;
if (arity != 2)
goto on_badarg;
/*
* The first element of the time is an erlang timestamp, which
* separates megasecs out, for whatever reason
*/
if (!enif_get_tuple(env, time_tuple[0], &arity, &time))
goto on_badarg;
if (arity != 3)
goto on_badarg;
if (!enif_get_uint(env, time[0], &megasecs))
goto on_badarg;
if (!enif_get_uint(env, time[1], &secs))
goto on_badarg;
if (!enif_get_int(env, time_tuple[1], &offset))
goto on_badarg;
gtime = megasecs * 1000000 + secs;
/* Finally we have all the data */
if (git_signature_new(&sig, (char *)name.data, (char *)email.data, gtime, offset) < 0) {
enif_release_binary(&name);
enif_release_binary(&email);
*err = geef_error(env);
return -1;
}
*out = sig;
return 0;
on_badarg:
enif_release_binary(&name);
enif_release_binary(&email);
*err = enif_make_badarg(env);
return -1;
on_oom:
enif_release_binary(&name);
enif_release_binary(&email);
*err = geef_oom(env);
return -1;
}
int geef_signature_to_erl(ERL_NIF_TERM *out, ErlNifEnv *env, const git_signature *sig)
{
ErlNifBinary name, email;
memset(&name, 0, sizeof(ErlNifBinary));
memset(&email, 0, sizeof(ErlNifBinary));
if (geef_string_to_bin(&name, sig->name) < 0)
goto oom;
if (geef_string_to_bin(&email, sig->email) < 0)
goto oom;
*out = 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));
return 0;
oom:
enif_release_binary(&name);
enif_release_binary(&email);
return -1;
}
ERL_NIF_TERM
geef_signature_default(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
git_signature *sig;
geef_repository *repo;
ERL_NIF_TERM term_sig;
int error;
if (!enif_get_resource(env, argv[0], geef_repository_type, (void **) &repo))
return enif_make_badarg(env);
if (git_signature_default(&sig, repo->repo) < 0)
return geef_error(env);
error = geef_signature_to_erl(&term_sig, env, sig);
git_signature_free(sig);
if (error < 0)
return geef_oom(env);
return term_sig;
}
ERL_NIF_TERM
geef_signature_new(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
ErlNifBinary name, email;
git_signature *sig;
size_t len;
int error;
unsigned int at;
if (!enif_inspect_iolist_as_binary(env, argv[0], &name))
return enif_make_badarg(env);
if (!enif_inspect_iolist_as_binary(env, argv[1], &email))
return enif_make_badarg(env);
if (argc == 3 && !enif_get_uint(env, argv[2], &at))
return enif_make_badarg(env);
if (!geef_terminate_binary(&name))
return atoms.error;
if (!geef_terminate_binary(&email)) {
enif_release_binary(&name);
return atoms.error;
}
if (argc == 3)
error = git_signature_now(&sig, (char *)name.data, (char *)email.data);
else
error = git_signature_new(&sig, (char *)name.data, (char *)email.data, at, 0);
if (error < 0)
return geef_error(env);
len = strlen(sig->name);
if (!enif_realloc_binary(&name, len))
goto on_error;
memcpy(name.data, sig->name, len);
len = strlen(sig->email);
if (!enif_realloc_binary(&email, len))
goto on_error;
memcpy(email.data, sig->email, len);
git_signature_free(sig);
if (argc == 3)
return enif_make_tuple3(env, atoms.ok, enif_make_binary(env, &name), enif_make_binary(env, &email));
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));
on_error:
git_signature_free(sig);
enif_release_binary(&name);
enif_release_binary(&email);
return atoms.error;
}