Skip to content

Commit

Permalink
OdbBackend: implement subclassed read_header
Browse files Browse the repository at this point in the history
  • Loading branch information
ddevault committed Oct 21, 2019
1 parent f4f4cd7 commit 6f38154
Showing 1 changed file with 97 additions and 8 deletions.
105 changes: 97 additions & 8 deletions src/odb_backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ struct py_odb_backend
git_odb_backend backend;
PyObject *self;
PyObject *read_callable,
*read_prefix_callable;
*read_prefix_callable,
*read_header_callable;
};

static int
Expand All @@ -65,7 +66,7 @@ py_odb_backend_read(void **ptr, size_t *sz,
return GIT_EUSER;

const char *bytes;
if (!PyArg_ParseTuple(result, "iy#", type, &bytes, sz) || !bytes)
if (!PyArg_ParseTuple(result, "ny#", type, &bytes, sz) || !bytes)
return GIT_EUSER;

/* XXX: This assumes the default libgit2 allocator is in use and will
Expand Down Expand Up @@ -100,7 +101,7 @@ py_odb_backend_read_prefix(git_oid *oid_out, void **ptr, size_t *sz,
return GIT_EUSER;

const char *bytes;
if (!PyArg_ParseTuple(result, "Oiy#",
if (!PyArg_ParseTuple(result, "Ony#",
&py_oid_out, type, &bytes, sz) || !bytes)
return GIT_EUSER;

Expand All @@ -115,10 +116,36 @@ py_odb_backend_read_prefix(git_oid *oid_out, void **ptr, size_t *sz,
return 0;
}

static int
py_odb_backend_read_header(size_t *len, git_object_t *type,
git_odb_backend *_be, const git_oid *oid)
{
int err;
PyObject *args, *py_oid, *result;
struct py_odb_backend *be = (struct py_odb_backend *)_be;

py_oid = git_oid_to_python(oid);
args = Py_BuildValue("(O)", py_oid);
result = PyObject_CallObject(be->read_header_callable, args);
Py_DECREF(py_oid);

if ((err = git_error_for_exc()) != 0) {
return err;
}

if (result == NULL)
return GIT_EUSER;

if (!PyArg_ParseTuple(result, "nn", type, len))
return GIT_EUSER;

return 0;
}

int
OdbBackend_init(OdbBackend *self, PyObject *args, PyObject *kwds)
{
if (kwds && PyTuple_Size(args) > 0) {
if (args && PyTuple_Size(args) > 0) {
PyErr_SetString(PyExc_TypeError,
"OdbBackend takes no arguments");
return -1;
Expand All @@ -135,18 +162,48 @@ OdbBackend_init(OdbBackend *self, PyObject *args, PyObject *kwds)
be->self = (PyObject *)self;

be->read_callable = PyObject_GetAttrString((PyObject *)self, "read");
if (be->read_callable)
if (be->read_callable) {
be->backend.read = py_odb_backend_read;
Py_INCREF(be->read_callable);
}

be->read_prefix_callable = PyObject_GetAttrString(
(PyObject *)self, "read_prefix");
if (be->read_prefix_callable)
if (be->read_prefix_callable) {
be->backend.read_prefix = py_odb_backend_read_prefix;
Py_INCREF(be->read_prefix_callable);
}

be->read_header_callable = PyObject_GetAttrString(
(PyObject *)self, "read_header");
if (be->read_header_callable) {
be->backend.read_header = py_odb_backend_read_header;
Py_INCREF(be->read_header_callable);
}

self->odb_backend = &be->backend;
self->odb_backend = (git_odb_backend *)be;
return 0;
}

void
OdbBackend_dealloc(OdbBackend *self)
{
if (self->odb_backend && self->odb_backend->read == py_odb_backend_read) {
struct py_odb_backend *be = (struct py_odb_backend *)self->odb_backend;

if (be->read_callable)
Py_DECREF(be->read_callable);
if (be->read_prefix_callable)
Py_DECREF(be->read_prefix_callable);
if (be->read_header_callable)
Py_DECREF(be->read_header_callable);

free(be);
}

Py_TYPE(self)->tp_free((PyObject *) self);
}

static int
OdbBackend_build_as_iter(const git_oid *oid, void *accum)
{
Expand Down Expand Up @@ -267,9 +324,41 @@ OdbBackend_read_prefix(OdbBackend *self, PyObject *py_hex)
return tuple;
}

PyDoc_STRVAR(OdbBackend_read_header__doc__,
"read_header(oid) -> (type, len)\n"
"\n"
"Read raw object header from this odb backend.\n");

PyObject *
OdbBackend_read_header(OdbBackend *self, PyObject *py_hex)
{
int err;
size_t len;
git_object_t type;
git_oid oid;

if (self->odb_backend->read_header == NULL) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}

len = py_oid_to_git_oid(py_hex, &oid);
if (len == 0)
return NULL;

err = self->odb_backend->read_header(&len, &type, self->odb_backend, &oid);
if (err != 0) {
Error_set_oid(err, &oid, len);
return NULL;
}

return Py_BuildValue("(ni)", type, len);
}

PyMethodDef OdbBackend_methods[] = {
METHOD(OdbBackend, read, METH_O),
METHOD(OdbBackend, read_prefix, METH_O),
METHOD(OdbBackend, read_header, METH_O),
{NULL}
};

Expand All @@ -280,7 +369,7 @@ PyTypeObject OdbBackendType = {
"_pygit2.OdbBackend", /* tp_name */
sizeof(OdbBackend), /* tp_basicsize */
0, /* tp_itemsize */
0, /* tp_dealloc */
(destructor)OdbBackend_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
Expand Down

0 comments on commit 6f38154

Please sign in to comment.