diff --git a/pygit2.c b/pygit2.c index 0c90d03..1d69c5a 100644 --- a/pygit2.c +++ b/pygit2.c @@ -50,6 +50,7 @@ typedef struct { OBJECT_STRUCT(Object, git_object, obj) OBJECT_STRUCT(Commit, git_commit, commit) OBJECT_STRUCT(Tree, git_tree, tree) +OBJECT_STRUCT(Blob, git_object, blob) typedef struct { PyObject_HEAD @@ -62,6 +63,7 @@ static PyTypeObject ObjectType; static PyTypeObject CommitType; static PyTypeObject TreeEntryType; static PyTypeObject TreeType; +static PyTypeObject BlobType; static int Repository_init(Repository *self, PyObject *args, PyObject *kwds) { @@ -118,7 +120,7 @@ static Object *wrap_object(git_object *obj, Repository *repo) { py_obj = (Object*)TreeType.tp_alloc(&TreeType, 0); break; case GIT_OBJ_BLOB: - py_obj = (Object*)ObjectType.tp_alloc(&ObjectType, 0); + py_obj = (Object*)BlobType.tp_alloc(&BlobType, 0); break; case GIT_OBJ_TAG: py_obj = (Object*)ObjectType.tp_alloc(&ObjectType, 0); @@ -918,6 +920,74 @@ static PyTypeObject TreeType = { 0, /* tp_new */ }; +static int +Blob_init(Blob *py_blob, PyObject *args, PyObject *kwds) { + Repository *repo = NULL; + git_object *blob; + + if (!object_init_check("blob", args, kwds, &repo)) + return -1; + + blob = git_object_new(repo->repo, GIT_OBJ_BLOB); + if (!blob) { + PyErr_SetNone(PyExc_MemoryError); + return -1; + } + Py_INCREF(repo); + py_blob->repo = repo; + py_blob->own_obj = 1; + py_blob->blob = blob; + return 0; +} + +/* TODO: libgit2 needs some way to set blob data. */ +static PyGetSetDef Blob_getseters[] = { + {"data", (getter)Object_read_raw, NULL, "raw data", NULL}, + {NULL} +}; + +static PyTypeObject BlobType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "pygit2.Blob", /*tp_name*/ + sizeof(Blob), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "Blob objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + Blob_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)Blob_init, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + static PyMethodDef module_methods[] = { {NULL} }; @@ -945,6 +1015,10 @@ initpygit2(void) TreeType.tp_new = PyType_GenericNew; if (PyType_Ready(&TreeType) < 0) return; + BlobType.tp_base = &ObjectType; + BlobType.tp_new = PyType_GenericNew; + if (PyType_Ready(&BlobType) < 0) + return; m = Py_InitModule3("pygit2", module_methods, "Python bindings for libgit2."); @@ -967,6 +1041,9 @@ initpygit2(void) Py_INCREF(&TreeType); PyModule_AddObject(m, "Tree", (PyObject *)&TreeType); + Py_INCREF(&BlobType); + PyModule_AddObject(m, "Blob", (PyObject *)&BlobType); + PyModule_AddIntConstant(m, "GIT_OBJ_ANY", GIT_OBJ_ANY); PyModule_AddIntConstant(m, "GIT_OBJ_COMMIT", GIT_OBJ_COMMIT); PyModule_AddIntConstant(m, "GIT_OBJ_TREE", GIT_OBJ_TREE); diff --git a/test/__init__.py b/test/__init__.py index 89b3d0c..e85e51b 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -36,7 +36,7 @@ import unittest def test_suite(): - names = ['commit', 'repository', 'tree'] + names = ['blob', 'commit', 'repository', 'tree'] modules = ['test.test_%s' % n for n in names] return unittest.defaultTestLoader.loadTestsFromNames(modules) diff --git a/test/test_blob.py b/test/test_blob.py new file mode 100644 index 0000000..2f66609 --- /dev/null +++ b/test/test_blob.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python +# +# Copyright 2010 Google, Inc. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, +# as published by the Free Software Foundation. +# +# In addition to the permissions in the GNU General Public License, +# the authors give you unlimited permission to link the compiled +# version of this file into combinations with other programs, +# and to distribute those combinations without any restriction +# coming from the use of this file. (The General Public License +# restrictions do apply in other respects; for example, they cover +# modification of the file, and distribution when not linked into +# a combined executable.) +# +# This file is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + +"""Tests for Blob objects.""" + +__author__ = 'dborowitz@google.com (Dave Borowitz)' + +import unittest + +import pygit2 +import utils + +BLOB_SHA = 'af431f20fc541ed6d5afede3e2dc7160f6f01f16' + + +class BlobTest(utils.TestRepoTestCase): + + def test_read_blob(self): + blob = self.repo[BLOB_SHA] + self.assertTrue(isinstance(blob, pygit2.Blob)) + self.assertEqual(pygit2.GIT_OBJ_BLOB, blob.type) + self.assertEqual('a contents\n', blob.data) + self.assertEqual('a contents\n', blob.read_raw()) + + +if __name__ == '__main__': + unittest.main()