summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--database.nobj.lua33
-rw-r--r--database_backend.nobj.lua185
-rw-r--r--git2.nobj.lua24
-rw-r--r--rawobject.nobj.lua11
-rw-r--r--test_backend.lua123
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")
+