diff options
author | Robert G. Jakabosky <bobby@sharedrealm.com> | 2011-01-07 14:06:46 -0800 |
---|---|---|
committer | Robert G. Jakabosky <bobby@sharedrealm.com> | 2011-01-07 14:06:46 -0800 |
commit | 588900de127f5b5024250d24e660dd5574870d50 (patch) | |
tree | 15d176c455054173df4b99cf619bf7154aa81279 | |
parent | 4c770c5b37de769fb50ccd81b11c51367f57d8ba (diff) | |
download | luagit2-588900de127f5b5024250d24e660dd5574870d50.tar.gz |
Added support for git_odb_backends. Improved RawObject code. Added Error codes for use by database backends.
-rw-r--r-- | database.nobj.lua | 33 | ||||
-rw-r--r-- | database_backend.nobj.lua | 185 | ||||
-rw-r--r-- | git2.nobj.lua | 24 | ||||
-rw-r--r-- | rawobject.nobj.lua | 11 | ||||
-rw-r--r-- | test_backend.lua | 123 |
5 files changed, 365 insertions, 11 deletions
diff --git a/database.nobj.lua b/database.nobj.lua index 014d346..487f0da 100644 --- a/database.nobj.lua +++ b/database.nobj.lua @@ -39,16 +39,27 @@ object "Database" { destructor "close" { c_call "void" "git_odb_close" {} }, - -- TODO: add_backend + method "add_backend" { + var_in{"DatabaseBackend *", "backend"}, + var_out{"GitError", "err"}, + c_source [[ + ${err} = git_odb_add_backend(${this}, &(${backend}->backend)); + DatabaseBackend_ref(${backend}); +]], + }, method "read" { var_in{"OID", "id"}, var_out{"RawObject *", "obj"}, var_out{"GitError", "err"}, c_source [[ - RawObject raw_obj; - raw_obj.ref = LUA_NOREF; - ${obj} = &(raw_obj); - ${err} = git_odb_read(&(raw_obj.raw), ${this}, &(${id})); + RawObject raw; + git_rawobj obj; + ${err} = git_odb_read(&(obj), ${this}, &(${id})); + if(${err} == GIT_SUCCESS) { + /* convert git_rawobj to RawObject */ + RawObject_from_git_rawobj(L, &raw, &obj); + ${obj} = &(raw); + } ]], }, method "read_header" { @@ -56,10 +67,14 @@ object "Database" { var_out{"RawObject *", "obj"}, var_out{"GitError", "err"}, c_source [[ - RawObject raw_obj; - raw_obj.ref = LUA_NOREF; - ${obj} = &(raw_obj); - ${err} = git_odb_read_header(&(raw_obj.raw), ${this}, &(${id})); + RawObject raw; + git_rawobj obj; + ${err} = git_odb_read_header(&(obj), ${this}, &(${id})); + if(${err} == GIT_SUCCESS) { + /* convert git_rawobj to RawObject */ + RawObject_from_git_rawobj(L, &raw, &obj); + ${obj} = &(raw); + } ]], }, method "write" { diff --git a/database_backend.nobj.lua b/database_backend.nobj.lua new file mode 100644 index 0000000..f0ccac6 --- /dev/null +++ b/database_backend.nobj.lua @@ -0,0 +1,185 @@ +-- Copyright (c) 2010 by Robert G. Jakabosky <bobby@sharedrealm.com> +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy +-- of this software and associated documentation files (the "Software"), to deal +-- in the Software without restriction, including without limitation the rights +-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +-- copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in +-- all copies or substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +-- THE SOFTWARE. + +c_source [[ +//typedef struct RawObject RawObject; +#include <git2/odb_backend.h> + +typedef struct DatabaseBackend { + git_odb_backend backend; + lua_State *L; + int read; + int read_header; + int write; + int exists; + int free; + int ref_count; +} DatabaseBackend; + +static void DatabaseBackend_ref(DatabaseBackend *backend) { + backend->ref_count++; +} + +static void DatabaseBackend_unref(DatabaseBackend *backend) { + lua_State *L = backend->L; + if((--backend->ref_count) == 0) { + luaL_unref(L, LUA_REGISTRYINDEX, backend->read); + luaL_unref(L, LUA_REGISTRYINDEX, backend->read_header); + luaL_unref(L, LUA_REGISTRYINDEX, backend->write); + luaL_unref(L, LUA_REGISTRYINDEX, backend->exists); + luaL_unref(L, LUA_REGISTRYINDEX, backend->free); + free(backend); + } +} + +static int database_backend_read_cb(git_rawobj *obj, git_odb_backend *backend, const git_oid *oid) +{ + DatabaseBackend *lua_backend = (DatabaseBackend *)backend; + lua_State *L = lua_backend->L; + int err; + + /* get Lua callback function. */ + lua_rawgeti(L, LUA_REGISTRYINDEX, lua_backend->read); + + obj_type_OID_push(L, *((OID *)oid), 0); + /* call Lua function. */ + lua_call(L, 1, 2); + err = lua_tointeger(L, -1); + if(err == 0) { + RawObject *raw_obj = obj_type_RawObject_check(L,-2); + *obj = raw_obj->raw; + } + + return err; +} + +static int database_backend_read_header_cb(git_rawobj *obj, git_odb_backend *backend, const git_oid *oid) +{ + DatabaseBackend *lua_backend = (DatabaseBackend *)backend; + lua_State *L = lua_backend->L; + int err; + + /* get Lua callback function. */ + lua_rawgeti(L, LUA_REGISTRYINDEX, lua_backend->read_header); + + obj_type_OID_push(L, *((OID *)oid), 0); + /* call Lua function. */ + lua_call(L, 1, 2); + err = lua_tointeger(L, -1); + if(err == 0) { + RawObject *raw_obj = obj_type_RawObject_check(L,-2); + *obj = raw_obj->raw; + } + + return err; +} + +static int database_backend_write_cb(git_oid *oid, git_odb_backend *backend, git_rawobj *obj) +{ + DatabaseBackend *lua_backend = (DatabaseBackend *)backend; + lua_State *L = lua_backend->L; + RawObject raw; + int err; + + /* get Lua callback function. */ + lua_rawgeti(L, LUA_REGISTRYINDEX, lua_backend->write); + + /* convert git_rawobj to RawObject */ + RawObject_from_git_rawobj(L, &raw, obj); + /* push RawObject onto stack. */ + obj_type_RawObject_push(L, &raw, 0); + + /* call Lua function. */ + lua_call(L, 1, 2); + err = lua_tointeger(L, -1); + if(err == 0) { + *oid = obj_type_OID_check(L,-2); + } + + return err; +} + +static int database_backend_exists_cb(git_odb_backend *backend, const git_oid *oid) +{ + DatabaseBackend *lua_backend = (DatabaseBackend *)backend; + lua_State *L = lua_backend->L; + + /* get Lua callback function. */ + lua_rawgeti(L, LUA_REGISTRYINDEX, lua_backend->exists); + + obj_type_OID_push(L, *((OID *)oid), 0); + /* call Lua function. */ + lua_call(L, 1, 1); + return lua_tointeger(L, -1); +} + +static void database_backend_free_cb(git_odb_backend *backend) +{ + DatabaseBackend *lua_backend = (DatabaseBackend *)backend; + lua_State *L = lua_backend->L; + + /* get Lua callback function. */ + lua_rawgeti(L, LUA_REGISTRYINDEX, lua_backend->free); + + /* call Lua function. */ + lua_call(L, 0, 0); + + DatabaseBackend_unref(lua_backend); +} + +]] + +object "DatabaseBackend" { + constructor { + var_in{"lua_State *", "L"}, + c_source [[ + int idx; + int ref; + int priority = luaL_optinteger(L, 2, 0); + + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 1); + /* create backend object. */ + ${this} = calloc(1, sizeof(DatabaseBackend)); + ${this}->ref_count = 1; + ${this}->L = L; + /* get each callback from table. */ +#define REF_CB(_name) \ + lua_getfield(L, 1, "on_" #_name); \ + ${this}->_name = luaL_ref(L, LUA_REGISTRYINDEX); \ + ${this}->backend._name = database_backend_ ## _name ## _cb; + + REF_CB(read) + REF_CB(read_header) + REF_CB(write) + REF_CB(exists) + REF_CB(free) +#undef REF_CB + + ${this}->backend.priority = priority; +]] + }, + destructor { + c_source [[ + DatabaseBackend_unref(${this}); +]] + }, +} + diff --git a/git2.nobj.lua b/git2.nobj.lua index 643636d..47e703a 100644 --- a/git2.nobj.lua +++ b/git2.nobj.lua @@ -6,13 +6,33 @@ hide_meta_info = false, --true, include "git2.h", +package "GIT" { +const "SUCCESS" { 0 }, +const "ERROR" { -1 }, +const "ENOTOID" { -2 }, +const "ENOTFOUND" { -3 }, +const "ENOMEM" { -4 }, +const "EOSERR" { -5 }, +const "EOBJTYPE" { -6 }, +const "EOBJCORRUPTED" { -7 }, +const "ENOTAREPO" { -8 }, +const "EINVALIDTYPE" { -9 }, +const "EMISSINGOBJDATA"{ -10 }, +const "EPACKCORRUPTED" { -11 }, +const "EFLOCKFAIL" { -12 }, +const "EZLIB" { -13 }, +const "EBUSY" { -14 }, +const "EBAREINDEX" { -15 }, +}, + subfiles { "repository.nobj.lua", -"database.nobj.lua", "rawobject.nobj.lua", +"oid.nobj.lua", +"database.nobj.lua", +"database_backend.nobj.lua", "index.nobj.lua", "index_entry.nobj.lua", -"oid.nobj.lua", "error.nobj.lua", "object.nobj.lua", "blob.nobj.lua", diff --git a/rawobject.nobj.lua b/rawobject.nobj.lua index 0e6e28e..6719567 100644 --- a/rawobject.nobj.lua +++ b/rawobject.nobj.lua @@ -44,6 +44,17 @@ static void RawObject_set_data_and_ref(lua_State *L, RawObject *obj, const char obj->ref = LUA_NOREF; } } + +static void RawObject_from_git_rawobj(lua_State *L, RawObject *raw, const git_rawobj *obj) { + /* push raw object's data onto stack. */ + lua_pushlstring(L, obj->data, obj->len); + /* get Lua's pointer to the string. */ + raw->raw.data = (void *)lua_tolstring(L, -1, &(raw->raw.len)); + raw->raw.type = obj->type; + /* get reference to string. */ + raw->ref = luaL_ref(L, LUA_REGISTRYINDEX); +} + ]] object "RawObject" { diff --git a/test_backend.lua b/test_backend.lua new file mode 100644 index 0000000..9708adf --- /dev/null +++ b/test_backend.lua @@ -0,0 +1,123 @@ +#!/usr/bin/env lua + +local build_dir = arg[1] +local git_path = arg[2] or "./test_rep/.git" +-- Make it easier to test +if ( build_dir ) then + package.cpath = build_dir .. "?.so;" .. package.cpath +end + +require"git2" +require"utils" + +local function dump_rawobj(obj) + print('dump RawObject:', obj) + if obj == nil then + return + end + print('hash = ', obj:hash()) + print('data = "' .. tostring(obj:data()) .. '"') + print('len = ', obj:len()) + print('type = ', obj:type()) +end + +-- create database +local db = assert(git2.Database.new()) +print("dump Database interface") +print(dbg_dump(db)) + +-- create backend +local obj_cache = {} +local function get_obj(oid) + print("------------------- exists callback:", oid) + if not oid then + return nil + end + -- convert oid to string. + oid = tostring(oid) + return obj_cache[oid] +end +local cbs = { +on_read = function(oid) + local raw_obj = nil + print("------------------- read callback:", oid) + raw_obj = get_obj(oid) + if not raw_obj then + return nil, git2.GIT.ENOTFOUND + end + return raw_obj, git2.GIT.SUCCESS +end, +on_read_header = function(oid) + local raw_obj = nil + print("------------------- read_header callback:", oid) + raw_obj = get_obj(oid) + if not raw_obj then + return nil, git2.GIT.ENOTFOUND + end + return raw_obj, git2.GIT.SUCCESS +end, +on_write = function(raw_obj) + local oid = raw_obj:hash() + print("------------------- write callback:", raw_obj) + if not oid then + return nil, -1 + end + -- convert oid to string. + local oid_str = tostring(oid) + -- put raw object in cache + obj_cache[oid_str] = raw_obj + return oid, git2.GIT.SUCCESS +end, +on_exists = function(oid) + local raw_obj = nil + print("------------------- exists callback:", oid) + raw_obj = get_obj(oid) + if not raw_obj then + return raw_obj, git2.GIT.ENOTFOUND + end + return git2.GIT.SUCCESS +end, +on_free = function() + print("------------------- free callback:") +end, +} + +local backend = git2.DatabaseBackend(cbs, 1) + +print('add backend:', assert(db:add_backend(backend))) + +print('create test blob:') +local raw_obj = git2.RawObject('blob',"any ol content will do") + +print("test writing RawObject to database:") +local oid, err = db:write(raw_obj) +print('write:', oid, err) + +print() +print("test reading RawObjects from database:") +local object_ids = { + {'tree', "31f3d5703ce27f0b63c3eb0d829abdc95b51deae"}, + {'commit', "d5a93c463d4cca0068750eb6af7b4b54eea8599b"}, + {'blob', "f534deb63f967cddd4bd440d05d3f6f075e55fca"}, + {'blob', "275a4019807c7bb7bc80c0ca8903bf84345e1bdf"}, +} +for _,obj in ipairs(object_ids) do + local oid = git2.OID.str(obj[2]) + local raw_obj, err = db:read(oid) + print('read', raw_obj, err) + dump_rawobj(raw_obj) + print() +end + +db = nil +backend = nil + +collectgarbage"collect" +collectgarbage"collect" +collectgarbage"collect" + + +print() +print() +print("finished") + |