/* * 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. */ #include <Python.h> #include <git/commit.h> #include <git/common.h> #include <git/repository.h> #include <git/commit.h> #include <git/odb.h> typedef struct { PyObject_HEAD git_repository *repo; } Repository; /* The structs for the various object subtypes are identical except for the type * of their object pointers. */ #define OBJECT_STRUCT(_name, _ptr_type, _ptr_name) \ typedef struct {\ PyObject_HEAD\ Repository *repo;\ int own_obj:1;\ _ptr_type *_ptr_name;\ } _name; OBJECT_STRUCT(Object, git_object, obj) OBJECT_STRUCT(Commit, git_commit, commit) OBJECT_STRUCT(Tree, git_tree, tree) typedef struct { PyObject_HEAD git_tree_entry *entry; Tree *tree; } TreeEntry; static PyTypeObject RepositoryType; static PyTypeObject ObjectType; static PyTypeObject CommitType; static PyTypeObject TreeEntryType; static PyTypeObject TreeType; static int Repository_init(Repository *self, PyObject *args, PyObject *kwds) { char *path; if (kwds) { PyErr_SetString(PyExc_TypeError, "Repository takes no keyword arugments"); return -1; } if (!PyArg_ParseTuple(args, "s", &path)) return -1; self->repo = git_repository_open(path); if (!self->repo) { PyErr_Format(PyExc_RuntimeError, "Failed to open repo directory at %s", path); return -1; } return 0; } static void Repository_dealloc(Repository *self) { if (self->repo) git_repository_free(self->repo); self->ob_type->tp_free((PyObject*)self); } static int Repository_contains(Repository *self, PyObject *value) { char *hex; git_oid oid; hex = PyString_AsString(value); if (!hex) return -1; if (git_oid_mkstr(&oid, hex) < 0) { PyErr_Format(PyExc_ValueError, "Invalid hex SHA \"%s\"", hex); return -1; } return git_odb_exists(git_repository_database(self->repo), &oid); } static Object *wrap_object(git_object *obj, Repository *repo) { Object *py_obj = NULL; switch (git_object_type(obj)) { case GIT_OBJ_COMMIT: py_obj = (Object*)CommitType.tp_alloc(&CommitType, 0); break; case GIT_OBJ_TREE: py_obj = (Object*)TreeType.tp_alloc(&TreeType, 0); break; case GIT_OBJ_BLOB: py_obj = (Object*)ObjectType.tp_alloc(&ObjectType, 0); break; case GIT_OBJ_TAG: py_obj = (Object*)ObjectType.tp_alloc(&ObjectType, 0); break; default: assert(0); } if (!py_obj) return NULL; py_obj->obj = obj; py_obj->repo = repo; Py_INCREF(repo); return py_obj; } static PyObject * Repository_getitem(Repository *self, PyObject *value) { char *hex; git_oid oid; git_object *obj; Object *py_obj; hex = PyString_AsString(value); if (!hex) return NULL; if (git_oid_mkstr(&oid, hex) < 0) { PyErr_Format(PyExc_ValueError, "Invalid hex SHA \"%s\"", hex); return NULL; } obj = git_repository_lookup(self->repo, &oid, GIT_OBJ_ANY); if (!obj) { PyErr_Format(PyExc_RuntimeError, "Failed to look up hex SHA \"%s\"", hex); return NULL; } py_obj = wrap_object(obj, self); if (!py_obj) return NULL; py_obj->own_obj = 0; return (PyObject*)py_obj; } static git_rawobj repository_raw_read(git_repository *repo, const git_oid *oid) { git_odb *db; git_rawobj raw; db = git_repository_database(repo); if (git_odb_read(&raw, db, oid) < 0) { PyErr_SetString(PyExc_RuntimeError, "Unable to read object"); return raw; } return raw; } static PyObject * Repository_read(Repository *self, PyObject *py_hex) { char *hex; git_oid id; git_rawobj raw; PyObject *result; hex = PyString_AsString(py_hex); if (!hex) { PyErr_SetString(PyExc_TypeError, "Expected string for hex SHA"); return NULL; } if (git_oid_mkstr(&id, hex) < 0) { PyErr_SetString(PyExc_ValueError, "Invalid hex SHA"); return NULL; } raw = repository_raw_read(self->repo, &id); if (!raw.data) { PyErr_Format(PyExc_RuntimeError, "Failed to read hex SHA \"%s\"", hex); return NULL; } result = Py_BuildValue("(ns#)", raw.type, raw.data, raw.len); free(raw.data); return result; } static PyMethodDef Repository_methods[] = { {"read", (PyCFunction)Repository_read, METH_O, "Read raw object data from the repository."}, {NULL, NULL, 0, NULL} }; static PySequenceMethods Repository_as_sequence = { 0, /* sq_length */ 0, /* sq_concat */ 0, /* sq_repeat */ 0, /* sq_item */ 0, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ (objobjproc)Repository_contains, /* sq_contains */ }; static PyMappingMethods Repository_as_mapping = { 0, /* mp_length */ (binaryfunc)Repository_getitem, /* mp_subscript */ 0, /* mp_ass_subscript */ }; static PyTypeObject RepositoryType = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "pygit2.Repository", /* tp_name */ sizeof(Repository), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)Repository_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ &Repository_as_sequence, /* tp_as_sequence */ &Repository_as_mapping, /* 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 */ "Git repository", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Repository_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)Repository_init, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ }; static void Object_dealloc(Object* self) { if (self->own_obj) git_object_free(self->obj); Py_XDECREF(self->repo); self->ob_type->tp_free((PyObject*)self); } static PyObject * Object_get_type(Object *self, void *closure) { return PyInt_FromLong(git_object_type(self->obj)); } static PyObject * Object_get_sha(Object *self, void *closure) { const git_oid *id; char hex[GIT_OID_HEXSZ]; id = git_object_id(self->obj); if (!id) return Py_None; git_oid_fmt(hex, id); return PyString_FromStringAndSize(hex, GIT_OID_HEXSZ); } static PyObject * Object_read_raw(Object *self) { const git_oid *id; git_rawobj raw; PyObject *result; id = git_object_id(self->obj); if (!id) return Py_None; /* in-memory object */ raw = repository_raw_read(git_object_owner(self->obj), id); if (!raw.data) { PyErr_SetString(PyExc_RuntimeError, "Failed to read object"); return NULL; } result = PyString_FromStringAndSize(raw.data, raw.len); free(raw.data); return result; } static PyObject * Object_write(Object *self) { if (git_object_write(self->obj) < 0) { PyErr_SetString(PyExc_RuntimeError, "Failed to write object to repo"); return NULL; } return Py_None; } static PyGetSetDef Object_getseters[] = { {"type", (getter)Object_get_type, NULL, "type number", NULL}, {"sha", (getter)Object_get_sha, NULL, "hex SHA", NULL}, {NULL} }; static PyMethodDef Object_methods[] = { {"read_raw", (PyCFunction)Object_read_raw, METH_NOARGS, "Read the raw contents of the object from the repo."}, {"write", (PyCFunction)Object_write, METH_NOARGS, "Write the object to the repo, if changed."}, {NULL} }; static PyTypeObject ObjectType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "pygit2.Object", /*tp_name*/ sizeof(Object), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Object_dealloc, /*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*/ "Object objects", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Object_methods, /* tp_methods */ 0, /* tp_members */ Object_getseters, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ }; static int object_init_check(const char *type_name, PyObject *args, PyObject *kwds, Repository **repo) { if (kwds) { PyErr_Format(PyExc_TypeError, "%s takes no keyword arugments", type_name); return 0; } if (!PyArg_ParseTuple(args, "O", repo)) return 0; if (!PyObject_TypeCheck(*repo, &RepositoryType)) { PyErr_SetString(PyExc_TypeError, "Expected Repository for repo"); return 0; } return 1; } static int Commit_init(Commit *py_commit, PyObject *args, PyObject *kwds) { Repository *repo = NULL; git_commit *commit; if (!object_init_check("Commit", args, kwds, &repo)) return -1; commit = git_commit_new(repo->repo); if (!commit) { PyErr_SetNone(PyExc_MemoryError); return -1; } Py_INCREF(repo); py_commit->repo = repo; py_commit->own_obj = 1; py_commit->commit = commit; return 0; } static PyObject * Commit_get_message_short(Commit *commit) { return PyString_FromString(git_commit_message_short(commit->commit)); } static PyObject * Commit_get_message(Commit *commit) { return PyString_FromString(git_commit_message(commit->commit)); } static int Commit_set_message(Commit *commit, PyObject *message) { if (!PyString_Check(message)) { PyErr_SetString(PyExc_TypeError, "Expected string for commit message."); return -1; } git_commit_set_message(commit->commit, PyString_AS_STRING(message)); return 0; } static PyObject * Commit_get_commit_time(Commit *commit) { return PyLong_FromLong(git_commit_time(commit->commit)); } static PyObject * Commit_get_committer(Commit *commit) { git_person *committer; committer = (git_person*)git_commit_committer(commit->commit); return Py_BuildValue("(ssl)", git_person_name(committer), git_person_email(committer), git_person_time(committer)); } static int Commit_set_committer(Commit *commit, PyObject *value) { char *name = NULL, *email = NULL; long long time; if (!PyArg_ParseTuple(value, "ssL", &name, &email, &time)) return -1; git_commit_set_committer(commit->commit, name, email, time); return 0; } static PyObject * Commit_get_author(Commit *commit) { git_person *author; author = (git_person*)git_commit_author(commit->commit); return Py_BuildValue("(ssl)", git_person_name(author), git_person_email(author), git_person_time(author)); } static int Commit_set_author(Commit *commit, PyObject *value) { char *name = NULL, *email = NULL; long long time; if (!PyArg_ParseTuple(value, "ssL", &name, &email, &time)) return -1; git_commit_set_author(commit->commit, name, email, time); return 0; } static PyGetSetDef Commit_getseters[] = { {"message_short", (getter)Commit_get_message_short, NULL, "short message", NULL}, {"message", (getter)Commit_get_message, (setter)Commit_set_message, "message", NULL}, {"commit_time", (getter)Commit_get_commit_time, NULL, "commit time", NULL}, {"committer", (getter)Commit_get_committer, (setter)Commit_set_committer, "committer", NULL}, {"author", (getter)Commit_get_author, (setter)Commit_set_author, "author", NULL}, {NULL} }; static PyTypeObject CommitType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "pygit2.Commit", /*tp_name*/ sizeof(Commit), /*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*/ "Commit 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 */ Commit_getseters, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)Commit_init, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ }; static void TreeEntry_dealloc(TreeEntry *self) { Py_XDECREF(self->tree); self->ob_type->tp_free((PyObject *)self); } static PyObject * TreeEntry_get_attributes(TreeEntry *self) { return PyInt_FromLong(git_tree_entry_attributes(self->entry)); } static int TreeEntry_set_attributes(TreeEntry *self, PyObject *value) { unsigned int attributes; attributes = PyInt_AsLong(value); if (PyErr_Occurred()) return -1; git_tree_entry_set_attributes(self->entry, attributes); return 0; } static PyObject * TreeEntry_get_name(TreeEntry *self) { return PyString_FromString(git_tree_entry_name(self->entry)); } static int TreeEntry_set_name(TreeEntry *self, PyObject *value) { char *name; name = PyString_AsString(value); if (!name) return -1; git_tree_entry_set_name(self->entry, name); return 0; } static PyObject * TreeEntry_get_sha(TreeEntry *self) { char hex[GIT_OID_HEXSZ]; git_oid_fmt(hex, git_tree_entry_id(self->entry)); return PyString_FromStringAndSize(hex, GIT_OID_HEXSZ); } static int TreeEntry_set_sha(TreeEntry *self, PyObject *value) { char *hex; git_oid oid; hex = PyString_AsString(value); if (!hex) return -1; if (git_oid_mkstr(&oid, hex) < 0) { PyErr_Format(PyExc_ValueError, "Invalid hex SHA \"%s\"", hex); return -1; } git_tree_entry_set_id(self->entry, &oid); return 0; } static PyObject * TreeEntry_to_object(TreeEntry *self) { git_object *obj; char hex[GIT_OID_HEXSZ]; PyObject *py_hex; obj = git_tree_entry_2object(self->entry); if (!obj) { git_oid_fmt(hex, git_tree_entry_id(self->entry)); py_hex = PyString_FromStringAndSize(hex, GIT_OID_HEXSZ); PyErr_SetObject(PyExc_KeyError, py_hex); return NULL; } return (PyObject*)wrap_object(obj, self->tree->repo); } static PyGetSetDef TreeEntry_getseters[] = { {"attributes", (getter)TreeEntry_get_attributes, (setter)TreeEntry_set_attributes, "attributes", NULL}, {"name", (getter)TreeEntry_get_name, (setter)TreeEntry_set_name, "name", NULL}, {"sha", (getter)TreeEntry_get_sha, (setter)TreeEntry_set_sha, "sha", NULL}, {NULL} }; static PyMethodDef TreeEntry_methods[] = { {"to_object", (PyCFunction)TreeEntry_to_object, METH_NOARGS, "Look up the corresponding object in the repo."}, {NULL, NULL, 0, NULL} }; static PyTypeObject TreeEntryType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "pygit2.TreeEntry", /*tp_name*/ sizeof(TreeEntry), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TreeEntry_dealloc, /*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*/ "TreeEntry objects", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TreeEntry_methods, /* tp_methods */ 0, /* tp_members */ TreeEntry_getseters, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ }; static int Tree_init(Tree *py_tree, PyObject *args, PyObject *kwds) { Repository *repo = NULL; git_tree *tree; if (!object_init_check("Tree", args, kwds, &repo)) return -1; tree = git_tree_new(repo->repo); if (!tree) { PyErr_SetNone(PyExc_MemoryError); return -1; } Py_INCREF(repo); py_tree->repo = repo; py_tree->own_obj = 1; py_tree->tree = tree; return 0; } static Py_ssize_t Tree_len(Tree *self) { return (Py_ssize_t)git_tree_entrycount(self->tree); } static int Tree_contains(Tree *self, PyObject *py_name) { char *name; name = PyString_AsString(py_name); return name && git_tree_entry_byname(self->tree, name) ? 1 : 0; } static TreeEntry * wrap_tree_entry(git_tree_entry *entry, Tree *tree) { TreeEntry *py_entry = NULL; py_entry = (TreeEntry*)TreeEntryType.tp_alloc(&TreeEntryType, 0); if (!py_entry) return NULL; py_entry->entry = entry; py_entry->tree = tree; Py_INCREF(tree); return py_entry; } static TreeEntry * Tree_getitem_by_name(Tree *self, PyObject *py_name) { char *name; git_tree_entry *entry; name = PyString_AS_STRING(py_name); entry = git_tree_entry_byname(self->tree, name); if (!entry) { PyErr_SetObject(PyExc_KeyError, py_name); return NULL; } return wrap_tree_entry(entry, self); } static int Tree_fix_index(Tree *self, PyObject *py_index) { long index; size_t len; long slen; index = PyInt_AsLong(py_index); if (PyErr_Occurred()) return -1; len = git_tree_entrycount(self->tree); slen = (long)len; if (index >= slen) { PyErr_SetObject(PyExc_IndexError, py_index); return -1; } else if (index < -slen) { PyErr_SetObject(PyExc_IndexError, py_index); return -1; } /* This function is called via mp_subscript, which doesn't do negative index * rewriting, so we have to do it manually. */ if (index < 0) index = len + index; return (int)index; } static TreeEntry * Tree_getitem_by_index(Tree *self, PyObject *py_index) { int index; git_tree_entry *entry; index = Tree_fix_index(self, py_index); if (PyErr_Occurred()) return NULL; entry = git_tree_entry_byindex(self->tree, index); if (!entry) { PyErr_SetObject(PyExc_IndexError, py_index); return NULL; } return wrap_tree_entry(entry, self); } static TreeEntry * Tree_getitem(Tree *self, PyObject *value) { if (PyString_Check(value)) { return Tree_getitem_by_name(self, value); } else if (PyInt_Check(value)) { return Tree_getitem_by_index(self, value); } else { PyErr_SetString(PyExc_TypeError, "Expected int or str for tree index."); return NULL; } } static int Tree_delitem_by_name(Tree *self, PyObject *name) { int err; err = git_tree_remove_entry_byname(self->tree, PyString_AS_STRING(name)); if (err < 0) { PyErr_SetObject(PyExc_KeyError, name); return -1; } return 0; } static int Tree_delitem_by_index(Tree *self, PyObject *py_index) { int index, err; index = Tree_fix_index(self, py_index); if (PyErr_Occurred()) return -1; err = git_tree_remove_entry_byindex(self->tree, index); if (err < 0) { PyErr_SetObject(PyExc_IndexError, py_index); return -1; } return 0; } static int Tree_delitem(Tree *self, PyObject *name, PyObject *value) { /* TODO: This function is only used for deleting items. We may be able to * come up with some reasonable assignment semantics, but it's tricky * because git_tree_entry objects are owned by their containing tree. */ if (value) { PyErr_SetString(PyExc_ValueError, "Cannot set TreeEntry directly; use add_entry."); return -1; } if (PyString_Check(name)) { return Tree_delitem_by_name(self, name); } else if (PyInt_Check(name)) { return Tree_delitem_by_index(self, name); } else { PyErr_SetString(PyExc_TypeError, "Expected int or str for tree index."); return -1; } } static PyObject * Tree_add_entry(Tree *self, PyObject *args) { char *hex, *name; int attributes; git_oid oid; if (!PyArg_ParseTuple(args, "ssi", &hex, &name, &attributes)) return NULL; if (git_oid_mkstr(&oid, hex) < 0) { PyErr_Format(PyExc_ValueError, "Invalid hex SHA \"%s\"", hex); return NULL; } if (git_tree_add_entry(self->tree, &oid, name, attributes) < 0) return PyErr_NoMemory(); return Py_None; } static PyMethodDef Tree_methods[] = { {"add_entry", (PyCFunction)Tree_add_entry, METH_VARARGS, "Add an entry to a Tree."}, {NULL} }; static PySequenceMethods Tree_as_sequence = { 0, /* sq_length */ 0, /* sq_concat */ 0, /* sq_repeat */ 0, /* sq_item */ 0, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ (objobjproc)Tree_contains, /* sq_contains */ }; static PyMappingMethods Tree_as_mapping = { (lenfunc)Tree_len, /* mp_length */ (binaryfunc)Tree_getitem, /* mp_subscript */ (objobjargproc)Tree_delitem, /* mp_ass_subscript */ }; static PyTypeObject TreeType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "pygit2.Tree", /*tp_name*/ sizeof(Tree), /*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*/ &Tree_as_sequence, /*tp_as_sequence*/ &Tree_as_mapping, /*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*/ "Tree objects", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Tree_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)Tree_init, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ }; static PyMethodDef module_methods[] = { {NULL} }; PyMODINIT_FUNC initpygit2(void) { PyObject* m; RepositoryType.tp_new = PyType_GenericNew; if (PyType_Ready(&RepositoryType) < 0) return; /* Do not set ObjectType.tp_new, to prevent creating Objects directly. */ if (PyType_Ready(&ObjectType) < 0) return; CommitType.tp_base = &ObjectType; CommitType.tp_new = PyType_GenericNew; if (PyType_Ready(&CommitType) < 0) return; TreeEntryType.tp_base = &ObjectType; TreeEntryType.tp_new = PyType_GenericNew; if (PyType_Ready(&TreeEntryType) < 0) return; TreeType.tp_base = &ObjectType; TreeType.tp_new = PyType_GenericNew; if (PyType_Ready(&TreeType) < 0) return; m = Py_InitModule3("pygit2", module_methods, "Python bindings for libgit2."); if (m == NULL) return; Py_INCREF(&RepositoryType); PyModule_AddObject(m, "Repository", (PyObject *)&RepositoryType); Py_INCREF(&ObjectType); PyModule_AddObject(m, "Object", (PyObject *)&ObjectType); Py_INCREF(&CommitType); PyModule_AddObject(m, "Commit", (PyObject *)&CommitType); Py_INCREF(&TreeEntryType); PyModule_AddObject(m, "TreeEntry", (PyObject *)&TreeEntryType); Py_INCREF(&TreeType); PyModule_AddObject(m, "Tree", (PyObject *)&TreeType); 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); PyModule_AddIntConstant(m, "GIT_OBJ_BLOB", GIT_OBJ_BLOB); PyModule_AddIntConstant(m, "GIT_OBJ_TAG", GIT_OBJ_TAG); }