summaryrefslogtreecommitdiff
path: root/src/odb_backend.nobj.lua
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 /src/odb_backend.nobj.lua
parent807aedec19955f0b7409e74a7562fe337038c302 (diff)
downloadluagit2-af56a49dc72ef1c4d12f43132d0dd6243b22129b.tar.gz
Fix support for ODB custom backends.
Diffstat (limited to 'src/odb_backend.nobj.lua')
-rw-r--r--src/odb_backend.nobj.lua236
1 files changed, 236 insertions, 0 deletions
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});
+]]
+ },
+}
+