From d71c6ff702e75247ce29c51279d78a7a202f5cc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 30 Jan 2013 00:16:52 +0100 Subject: [PATCH] Add a way to look up objects --- c_src/geef.c | 13 ++++++++++ c_src/geef.h | 4 +++ c_src/object.c | 62 ++++++++++++++++++++++++++++++++++++++++++++ c_src/object.h | 17 ++++++++++++ src/geef.erl | 6 +++++ src/geef_object.erl | 14 ++++++++++ src/geef_records.hrl | 2 ++ 7 files changed, 118 insertions(+) create mode 100644 c_src/object.c create mode 100644 c_src/object.h create mode 100644 src/geef_object.erl diff --git a/c_src/geef.c b/c_src/geef.c index 8d8dc5d..59cbe57 100644 --- a/c_src/geef.c +++ b/c_src/geef.c @@ -2,6 +2,7 @@ #include "repository.h" #include "reference.h" #include "oid.h" +#include "object.h" #include "geef.h" #include #include @@ -10,6 +11,7 @@ ErlNifResourceType *geef_repository_type; ErlNifResourceType *geef_odb_type; ErlNifResourceType *geef_ref_type; +ErlNifResourceType *geef_object_type; geef_atoms atoms; @@ -35,6 +37,12 @@ static int load(ErlNifEnv *env, void **priv, ERL_NIF_TERM load_info) if (geef_ref_type == NULL) return -1; + geef_object_type = enif_open_resource_type(env, NULL, + "object_type", geef_object_free, ERL_NIF_RT_CREATE, NULL); + if (geef_repository_type == NULL) + return -1; + + atoms.ok = enif_make_atom(env, "ok"); atoms.error = enif_make_atom(env, "error"); atoms.true = enif_make_atom(env, "true"); @@ -42,6 +50,10 @@ static int load(ErlNifEnv *env, void **priv, ERL_NIF_TERM load_info) atoms.repository = enif_make_atom(env, "repository"); atoms.oid = enif_make_atom(env, "oid"); atoms.symbolic = enif_make_atom(env, "symbolic"); + atoms.commit = enif_make_atom(env, "commit"); + atoms.tree = enif_make_atom(env, "tree"); + atoms.blob = enif_make_atom(env, "blob"); + atoms.tag = enif_make_atom(env, "tag"); return 0; } @@ -84,6 +96,7 @@ static ErlNifFunc geef_funcs[] = {"reference_type", 1, geef_reference_type}, {"oid_fmt", 1, geef_oid_fmt}, {"oid_parse", 1, geef_oid_parse}, + {"object_lookup", 2, geef_object_lookup}, }; ERL_NIF_INIT(geef, geef_funcs, load, NULL, NULL, unload) diff --git a/c_src/geef.h b/c_src/geef.h index 5dfda32..8265f2f 100644 --- a/c_src/geef.h +++ b/c_src/geef.h @@ -13,6 +13,10 @@ typedef struct { ERL_NIF_TERM repository; ERL_NIF_TERM oid; ERL_NIF_TERM symbolic; + ERL_NIF_TERM commit; + ERL_NIF_TERM tree; + ERL_NIF_TERM blob; + ERL_NIF_TERM tag; } geef_atoms; extern geef_atoms atoms; diff --git a/c_src/object.c b/c_src/object.c new file mode 100644 index 0000000..adcaf97 --- /dev/null +++ b/c_src/object.c @@ -0,0 +1,62 @@ +#include "geef.h" +#include "repository.h" +#include "object.h" +#include "oid.h" +#include +#include + +void geef_object_free(ErlNifEnv *env, void *cd) +{ + geef_object *obj = (geef_object *) cd; + git_object_free(obj->obj); +} + +static ERL_NIF_TERM object_type(git_object *obj) +{ + switch(git_object_type(obj)) { + case GIT_OBJ_COMMIT: + return atoms.commit; + case GIT_OBJ_TREE: + return atoms.tree; + case GIT_OBJ_BLOB: + return atoms.blob; + case GIT_OBJ_TAG: + return atoms.tag; + default: + return atoms.error; + } +} + +ERL_NIF_TERM +geef_object_lookup(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) +{ + geef_repository *repo; + ErlNifBinary bin; + git_oid id; + geef_object *obj; + ERL_NIF_TERM term_obj; + + if (!enif_get_resource(env, argv[0], geef_repository_type, (void **) &repo)) + return enif_make_badarg(env); + + if (!enif_inspect_binary(env, argv[1], &bin)) + return enif_make_badarg(env); + + if (bin.size < GIT_OID_RAWSZ) + return enif_make_badarg(env); + + git_oid_fromraw(&id, bin.data); + + obj = enif_alloc_resource(geef_object_type, sizeof(geef_object)); + if (git_object_lookup(&obj->obj, repo->repo, &id, GIT_OBJ_ANY) < 0) { + enif_release_resource(obj); + return geef_error(env); + } + + + term_obj = enif_make_resource(env, obj); + enif_release_resource(obj); + + + return enif_make_tuple3(env, atoms.ok, object_type(obj->obj), term_obj); +} diff --git a/c_src/object.h b/c_src/object.h new file mode 100644 index 0000000..15be0d9 --- /dev/null +++ b/c_src/object.h @@ -0,0 +1,17 @@ +#ifndef GEEF_OBJECT_H +#define GEEF_OBJECT_H + +#include "erl_nif.h" +#include + +extern ErlNifResourceType *geef_object_type; + +typedef struct { + git_object *obj; +} geef_object; + +ERL_NIF_TERM geef_object_lookup(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); + +void geef_object_free(ErlNifEnv *env, void *cd); + +#endif diff --git a/src/geef.erl b/src/geef.erl index 485053f..f0bbeb5 100644 --- a/src/geef.erl +++ b/src/geef.erl @@ -10,6 +10,9 @@ % oid parsing -export([oid_fmt/1, oid_parse/1]). +% objects +-export([object_lookup/2]). + -on_load(load_enif/0). hex_to_raw(_Val) -> @@ -68,6 +71,9 @@ oid_fmt(_Oid) -> oid_parse(_Sha) -> nif_error(?LINE). +object_lookup(_Repo, _Oid) -> + nif_error(?LINE). + nif_error(Line) -> erlang:nif_error({nif_not_loaded,module,?MODULE,line,Line}). diff --git a/src/geef_object.erl b/src/geef_object.erl new file mode 100644 index 0000000..5fe4a0e --- /dev/null +++ b/src/geef_object.erl @@ -0,0 +1,14 @@ +-module(geef_object). + +-include("geef_records.hrl"). + +-export([lookup/2]). + +-spec lookup(repo(), oid()) -> object(). +lookup(#repo{handle=Repo}, #oid{oid=Oid}) -> + case geef:object_lookup(Repo, Oid) of + {ok, Type, Handle} -> + #object{type=Type, handle=Handle}; + Other -> + Other + end. diff --git a/src/geef_records.hrl b/src/geef_records.hrl index a1e7971..a8eb869 100644 --- a/src/geef_records.hrl +++ b/src/geef_records.hrl @@ -2,8 +2,10 @@ -record(repo, {handle}). -record(odb, {handle}). -record(oid, {oid}). +-record(object, {type :: atom(), handle}). -type ref() :: #ref{}. -type repo() :: #repo{}. -type odb() :: #odb{}. -type oid() :: #oid{}. +-type object() :: #object{}.