diff --git a/src/odb_backend.c b/src/odb_backend.c index e4322506..dbf46b36 100644 --- a/src/odb_backend.c +++ b/src/odb_backend.c @@ -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 @@ -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 @@ -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; @@ -115,6 +116,32 @@ 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) { @@ -143,6 +170,11 @@ OdbBackend_init(OdbBackend *self, PyObject *args, PyObject *kwds) if (be->read_prefix_callable) be->backend.read_prefix = py_odb_backend_read_prefix; + be->read_header_callable = PyObject_GetAttrString( + (PyObject *)self, "read_header"); + if (be->read_header_callable) + be->backend.read_header = py_odb_backend_read_header; + self->odb_backend = &be->backend; return 0; } @@ -267,9 +299,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} };