summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert G. Jakabosky <bobby@sharedrealm.com>2012-05-11 22:47:08 -0700
committerRobert G. Jakabosky <bobby@sharedrealm.com>2012-05-11 22:47:08 -0700
commitaf56a49dc72ef1c4d12f43132d0dd6243b22129b (patch)
treeb06a4a6c65b3441a99aea2af5029618f877f9e4b
parent807aedec19955f0b7409e74a7562fe337038c302 (diff)
downloadluagit2-af56a49dc72ef1c4d12f43132d0dd6243b22129b.tar.gz
Fix support for ODB custom backends.
-rw-r--r--git2.nobj.lua2
-rw-r--r--src/database_backend.nobj.lua198
-rw-r--r--src/object.nobj.lua6
-rw-r--r--src/odb.nobj.lua2
-rw-r--r--src/odb_backend.nobj.lua236
-rw-r--r--tests/test_backend.lua90
6 files changed, 291 insertions, 243 deletions
diff --git a/git2.nobj.lua b/git2.nobj.lua
index 8ad1b29..fac7d14 100644
--- a/git2.nobj.lua
+++ b/git2.nobj.lua
@@ -64,7 +64,7 @@ subfiles {
"src/oid.nobj.lua",
"src/oid_shorten.nobj.lua",
"src/odb.nobj.lua",
---"src/database_backend.nobj.lua",
+"src/odb_backend.nobj.lua",
"src/index.nobj.lua",
"src/index_entry.nobj.lua",
"src/index_entry_unmerged.nobj.lua",
diff --git a/src/database_backend.nobj.lua b/src/database_backend.nobj.lua
deleted file mode 100644
index 57c83c3..0000000
--- a/src/database_backend.nobj.lua
+++ /dev/null
@@ -1,198 +0,0 @@
--- 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.
-
-object "DatabaseBackend" {
- 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);
- /* copy header fields. */
- obj->len = raw_obj->git.len;
- obj->type = raw_obj->git.type;
- /* we must malloc & copy the RawObject's data. */
- if(raw_obj->git.data) {
- obj->data = malloc(obj->len);
- if(obj->data == NULL) {
- /* failed to allocate buffer. */
- return GIT_ENOMEM;
- }
- /* copy data. */
- memcpy(obj->data, raw_obj->git.data, obj->len);
- } else {
- obj->data = NULL;
- }
- }
-
- 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);
- /* copy only header fields. */
- obj->data = NULL;
- obj->len = raw_obj->git.len;
- obj->type = raw_obj->git.type;
- }
-
- 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, 0);
- /* 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);
-}
-
-]],
- constructor {
- var_in{"lua_State *", "L"},
- c_source [[
- int idx;
- int ref;
-
- 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
-]]
- },
- destructor {
- c_source [[
- DatabaseBackend_unref(${this});
-]]
- },
-}
-
diff --git a/src/object.nobj.lua b/src/object.nobj.lua
index 30658bf..b8e5cb9 100644
--- a/src/object.nobj.lua
+++ b/src/object.nobj.lua
@@ -46,5 +46,11 @@ typedef git_object Object;
method "owner" {
c_method_call "Repository *" "git_object_owner" {}
},
+ c_function "type2string" {
+ c_call "const char *" "git_object_type2string" { "git_otype", "otype" },
+ },
+ c_function "string2type" {
+ c_call "git_otype" "git_object_string2type" { "const char *", "str" },
+ },
}
diff --git a/src/odb.nobj.lua b/src/odb.nobj.lua
index 1d706b4..d68d159 100644
--- a/src/odb.nobj.lua
+++ b/src/odb.nobj.lua
@@ -32,7 +32,6 @@ typedef git_odb ODB;
destructor "free" {
c_method_call "void" "git_odb_free" {}
},
- --[=[
method "add_backend" {
var_in{"ODBBackend *", "backend"},
var_in{"int", "priority"},
@@ -51,7 +50,6 @@ typedef git_odb ODB;
ODBBackend_ref(${backend});
]],
},
- --]=]
method "read" {
c_call "GitError" "git_odb_read"
{ "!OdbObject *", "&out>1", "ODB *", "this", "OID", "&id"},
diff --git a/src/odb_backend.nobj.lua b/src/odb_backend.nobj.lua
new file mode 100644
index 0000000..4e8d9a5
--- /dev/null
+++ b/src/odb_backend.nobj.lua
@@ -0,0 +1,236 @@
+-- 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.
+
+object "ODBBackend" {
+ c_source [[
+#include <git2/odb_backend.h>
+
+typedef struct ODBBackend {
+ git_odb_backend backend;
+ lua_State *L;
+ int read;
+ int read_prefix;
+ int read_header;
+ int write;
+ int exists;
+ int free;
+ int ref_count;
+} ODBBackend;
+
+static void ODBBackend_ref(ODBBackend *backend) {
+ backend->ref_count++;
+}
+
+static void ODBBackend_unref(ODBBackend *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_prefix);
+ 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 odb_backend_read_cb(void **data_p, size_t *len_p, git_otype *type_p, git_odb_backend *backend, const git_oid *oid)
+{
+ ODBBackend *lua_backend = (ODBBackend *)backend;
+ lua_State *L = lua_backend->L;
+ const char *ldata;
+ size_t len;
+ int err;
+
+ /* get Lua callback function. */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, lua_backend->read);
+
+ obj_type_OID_push(L, *((OID *)oid));
+ /* call Lua function. */
+ lua_call(L, 1, 2);
+ ldata = lua_tolstring(L, -2, &len);
+ if(ldata) {
+ char *data;
+ /* parse otype value. */
+ int arg_type = lua_type(L, -1);
+ if(arg_type == LUA_TNUMBER) {
+ *type_p = lua_tointeger(L, -1);
+ } else if(arg_type == LUA_TSTRING) {
+ *type_p = git_object_string2type(lua_tostring(L, -1));
+ }
+ *len_p = len;
+ /* allocate buffer for data. */
+ data = malloc(len);
+ *data_p = data;
+ if(data == NULL) {
+ return GIT_ENOMEM;
+ }
+ /* copy data. */
+ memcpy(data, ldata, len);
+ err = GIT_SUCCESS;
+ } else if(lua_isnil(L, -2)) {
+ *data_p = NULL;
+ /* backend returned an error. */
+ err = lua_tointeger(L, -1);
+ } else {
+ *data_p = NULL;
+ /* bad return value from lua backend. */
+ err = GIT_EOBJTYPE;
+ }
+
+ return err;
+}
+
+static int odb_backend_read_prefix_cb(git_oid *out_oid, void **data_p, size_t *len_p, git_otype *type_p, git_odb_backend *backend, const git_oid *short_oid, unsigned int len)
+{
+ *data_p = NULL;
+ if(len >= GIT_OID_HEXSZ) {
+ int rc = odb_backend_read_cb(data_p, len_p, type_p, backend, short_oid);
+ if(rc == GIT_SUCCESS) {
+ git_oid_cpy(out_oid, short_oid);
+ }
+ return rc;
+ }
+ return GIT_ENOTIMPLEMENTED;
+}
+
+static int odb_backend_read_header_cb(size_t *len_p, git_otype *type_p, git_odb_backend *backend, const git_oid *oid)
+{
+ ODBBackend *lua_backend = (ODBBackend *)backend;
+ lua_State *L = lua_backend->L;
+ int err;
+ int arg_type;
+
+ /* get Lua callback function. */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, lua_backend->read_header);
+
+ obj_type_OID_push(L, *((OID *)oid));
+ /* call Lua function. */
+ lua_call(L, 1, 2);
+
+ arg_type = lua_type(L, -2);
+ if(arg_type == LUA_TSTRING || arg_type == LUA_TNUMBER) {
+ /* parse data length. */
+ *len_p = lua_tonumber(L, -2);
+ /* parse otype value. */
+ lua_type(L, -1);
+ if(arg_type == LUA_TNUMBER) {
+ *type_p = lua_tointeger(L, -1);
+ } else if(arg_type == LUA_TSTRING) {
+ *type_p = git_object_string2type(lua_tostring(L, -1));
+ }
+ err = GIT_SUCCESS;
+ } else if(arg_type == LUA_TNIL) {
+ /* backend returned an error. */
+ err = lua_tointeger(L, -1);
+ } else {
+ /* bad return value from lua backend. */
+ err = GIT_EOBJTYPE;
+ }
+
+ return err;
+}
+
+static int odb_backend_write_cb(git_oid *oid, git_odb_backend *backend, const void *data, size_t len, git_otype type)
+{
+ ODBBackend *lua_backend = (ODBBackend *)backend;
+ lua_State *L = lua_backend->L;
+ int err;
+
+ /* get Lua callback function. */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, lua_backend->write);
+
+ /* push data onto stack. */
+ lua_pushlstring(L, data, len);
+ /* push otype */
+ lua_pushstring(L, git_object_type2string(type));
+
+ /* call Lua function. */
+ lua_call(L, 2, 2);
+ if(!lua_isnil(L, -2)) {
+ *oid = obj_type_OID_check(L,-2);
+ err = GIT_SUCCESS;
+ } else {
+ err = lua_tointeger(L, -1);
+ }
+
+ return err;
+}
+
+static int odb_backend_exists_cb(git_odb_backend *backend, const git_oid *oid)
+{
+ ODBBackend *lua_backend = (ODBBackend *)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));
+ /* call Lua function. */
+ lua_call(L, 1, 1);
+ return lua_tointeger(L, -1);
+}
+
+static void odb_backend_free_cb(git_odb_backend *backend)
+{
+ ODBBackend *lua_backend = (ODBBackend *)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);
+
+ ODBBackend_unref(lua_backend);
+}
+
+]],
+ constructor {
+ var_in{"lua_State *", "L"},
+ c_source [[
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_settop(L, 1);
+ /* create backend object. */
+ ${this} = calloc(1, sizeof(ODBBackend));
+ ${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 = odb_backend_ ## _name ## _cb;
+
+ REF_CB(read)
+ REF_CB(read_prefix)
+ REF_CB(read_header)
+ REF_CB(write)
+ REF_CB(exists)
+ REF_CB(free)
+#undef REF_CB
+]]
+ },
+ destructor {
+ c_source [[
+ ODBBackend_unref(${this});
+]]
+ },
+}
+
diff --git a/tests/test_backend.lua b/tests/test_backend.lua
index 1af0c72..ba0633a 100644
--- a/tests/test_backend.lua
+++ b/tests/test_backend.lua
@@ -7,24 +7,23 @@ if ( build_dir ) then
package.cpath = build_dir .. "?.so;" .. package.cpath
end
-require"git2"
+local git2 = require"git2"
require"utils"
print(dump(git2))
-local function dump_rawobj(obj)
- print('dump RawObject:', obj)
+local function dump_obj(obj)
+ print('dump OdbObject:', obj)
if obj == nil then
return
end
- print('hash = ', obj:hash())
- print('data = "' .. tostring(obj:data()) .. '"')
- print('len = ', obj:len())
+ print('id = ', obj:id())
print('type = ', obj:type())
end
--- create database
-local db = assert(git2.Database.new())
-print("dump Database interface")
+-- create odb
+local db = assert(git2.ODB.new())
+print("=============================================== new db=", db)
+print("dump ODB interface")
print(dbg_dump(db))
-- create backend
@@ -40,62 +39,67 @@ local function get_obj(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
+ local obj = get_obj(oid)
+ if not obj then
return nil, git2.ENOTFOUND
end
- return raw_obj, git2.SUCCESS
+ return obj.data, obj.otype
+end,
+on_read_prefix = function(short_oid, len)
+ print("------------------- read_prefix callback:", oid)
+ local obj = get_obj(short_oid)
+ if not obj then
+ if len ~= git2.OID.HEXSZ then
+ return nil, git2.ENOTIMPLEMENTED
+ end
+ return nil, git2.ENOTFOUND
+ end
+ return obj.data, obj.otype, short_oid
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
+ local obj = get_obj(oid)
+ if not obj then
return nil, git2.ENOTFOUND
end
- return raw_obj, git2.SUCCESS
+ return obj.len, obj.otype
end,
-on_write = function(raw_obj)
- local oid = raw_obj:hash()
- print("------------------- write callback:", raw_obj)
+on_write = function(data, otype)
+ local oid = git2.ODB.hash(data, git2.Object.string2type(otype))
+ print("------------------- write callback:", data, otype)
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.SUCCESS
+ obj_cache[oid_str] = { data = data, len = #data, otype = otype}
+ return oid
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.ENOTFOUND
+ local obj = get_obj(oid)
+ if not obj then
+ return false
end
- return git2.SUCCESS
+ return true
end,
on_free = function()
print("------------------- free callback:")
end,
}
-local backend = git2.DatabaseBackend(cbs)
+local backend = git2.ODBBackend(cbs)
print('add backend:', assert(db:add_backend(backend, 0)))
-print('create test blob:')
-local raw_obj = git2.RawObject.new('blob',"any ol content will do")
-
-print("test writing RawObject to database:")
-local oid, err = db:write(raw_obj)
+print("test writing test blob to odb:")
+local oid, err = db:write("any ol content will do", 'blob')
print('write:', oid, err)
print()
-print("test reading RawObjects from database:")
+print("test reading RawObjects from odb:")
local object_ids = {
{'tree', "31f3d5703ce27f0b63c3eb0d829abdc95b51deae"},
{'commit', "d5a93c463d4cca0068750eb6af7b4b54eea8599b"},
@@ -103,10 +107,10 @@ local object_ids = {
{'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)
+ local oid = git2.OID.hex(obj[2])
+ local obj, err = db:read(oid)
+ print('read', obj, err)
+ dump_obj(obj)
print()
end
@@ -119,9 +123,10 @@ if not status then
else
print("Created repository with no backends from git repository:", git_path)
end
-db = rep:database()
-backend = git2.DatabaseBackend(cbs)
-print("add backend repository's database:", assert(db:add_backend(backend, 0)))
+db = rep:odb()
+print("=============================================== repo db=", db)
+backend = git2.ODBBackend(cbs)
+print("add backend repository's odb:", assert(db:add_backend(backend, 0)))
print()
print("try reading objects from repository:")
@@ -132,7 +137,7 @@ local object_ids = {
{'blob', "275a4019807c7bb7bc80c0ca8903bf84345e1bdf"},
}
for _,obj in ipairs(object_ids) do
- local oid = git2.OID.str(obj[2])
+ local oid = git2.OID.hex(obj[2])
local obj, err = rep:lookup(oid, obj[1])
print('read', obj, err)
print()
@@ -140,6 +145,7 @@ end
db = nil
backend = nil
+obj_cache = nil
collectgarbage"collect"
collectgarbage"collect"