diff options
author | Robert G. Jakabosky <bobby@sharedrealm.com> | 2012-05-11 22:47:08 -0700 |
---|---|---|
committer | Robert G. Jakabosky <bobby@sharedrealm.com> | 2012-05-11 22:47:08 -0700 |
commit | af56a49dc72ef1c4d12f43132d0dd6243b22129b (patch) | |
tree | b06a4a6c65b3441a99aea2af5029618f877f9e4b /src/odb_backend.nobj.lua | |
parent | 807aedec19955f0b7409e74a7562fe337038c302 (diff) | |
download | luagit2-af56a49dc72ef1c4d12f43132d0dd6243b22129b.tar.gz |
Fix support for ODB custom backends.
Diffstat (limited to 'src/odb_backend.nobj.lua')
-rw-r--r-- | src/odb_backend.nobj.lua | 236 |
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}); +]] + }, +} + |