Merge remote branch 'byron/repo_write_improved' into repo_write

This commit is contained in:
J. David Ibáñez 2011-07-18 22:45:46 +02:00
commit cd83372230
2 changed files with 69 additions and 1 deletions

@ -169,7 +169,7 @@ Error_set_py_obj(int err, PyObject *py_obj) {
assert(err < 0);
if (err == GIT_ENOTOID && !PyString_Check(py_obj)) {
PyErr_Format(PyExc_TypeError, "Git object id must be str, not %.200s",
PyErr_Format(PyExc_TypeError, "Git object id must be 40 byte hexadecimal str, or 20 byte binary str: %.200s",
py_obj->ob_type->tp_name);
return NULL;
} else if (err == GIT_ENOTFOUND) {
@ -223,6 +223,18 @@ lookup_object(Repository *repo, const git_oid *oid, git_otype type) {
return (PyObject*)py_obj;
}
static git_otype
int_to_loose_object_type(int type_id)
{
switch((git_otype)type_id) {
case GIT_OBJ_COMMIT: return GIT_OBJ_COMMIT;
case GIT_OBJ_TREE: return GIT_OBJ_TREE;
case GIT_OBJ_BLOB: return GIT_OBJ_BLOB;
case GIT_OBJ_TAG: return GIT_OBJ_TAG;
default: return GIT_OBJ_BAD;
}
}
static PyObject *
wrap_reference(git_reference * c_reference)
{
@ -261,6 +273,16 @@ py_str_to_git_oid(PyObject *py_str, git_oid *oid) {
return 1;
}
static PyObject*
git_oid_to_py_string(git_oid* oid)
{
char buf[GIT_OID_HEXSZ+1];
if (strlen(git_oid_to_string(buf, sizeof(buf), oid)) != GIT_OID_HEXSZ)
return NULL;
return PyString_FromStringAndSize(buf, GIT_OID_HEXSZ);
}
static int
Repository_init(Repository *self, PyObject *args, PyObject *kwds) {
char *path;
@ -341,6 +363,37 @@ Repository_read(Repository *self, PyObject *py_hex) {
return tuple;
}
static PyObject *
Repository_write(Repository *self, PyObject *args)
{
int err;
git_oid oid;
git_odb_stream* stream;
int type_id;
const char* buffer;
Py_ssize_t buflen;
if (!PyArg_ParseTuple(args, "Is#", &type_id, &buffer, &buflen))
return NULL;
git_otype type = int_to_loose_object_type(type_id);
if (type == GIT_OBJ_BAD)
return Error_set_str(-100, "Invalid object type");
git_odb* odb = git_repository_database(self->repo);
if ((err = git_odb_open_wstream(&stream, odb, buflen, type)) == GIT_SUCCESS) {
stream->write(stream, buffer, buflen);
err = stream->finalize_write(&oid, stream);
stream->free(stream);
}
if (err < 0)
return Error_set_str(err, "failed to write data");
return git_oid_to_py_string(&oid);
}
static PyObject *
Repository_get_index(Repository *self, void *closure) {
int err;
@ -689,6 +742,10 @@ static PyMethodDef Repository_methods[] = {
"Generator that traverses the history starting from the given commit."},
{"read", (PyCFunction)Repository_read, METH_O,
"Read raw object data from the repository."},
{"write", (PyCFunction)Repository_write, METH_VARARGS,
"Write raw object data into the repository. First arg is the object type number, \n\
the second one a buffer with data.\n\
Return the hexadecimal sha of the created object"},
{"listall_references", (PyCFunction)Repository_listall_references,
METH_VARARGS,
"Return a list with all the references that can be found in a "

@ -53,6 +53,17 @@ class RepositoryTest(utils.BareRepoTestCase):
a2 = self.repo.read('7f129fd57e31e935c6d60a0c794efe4e6927664b')
self.assertEqual((pygit2.GIT_OBJ_BLOB, 'a contents 2\n'), a2)
def test_write(self):
data = "hello world"
# invalid object type
self.assertRaises(pygit2.GitError, self.repo.write, pygit2.GIT_OBJ_ANY, data)
hex_sha = self.repo.write(pygit2.GIT_OBJ_BLOB, data)
self.assertEqual(len(hex_sha), 40)
# works as buffer as well
self.assertEqual(hex_sha, self.repo.write(pygit2.GIT_OBJ_BLOB, buffer(data)))
def test_contains(self):
self.assertRaises(TypeError, lambda: 123 in self.repo)