Dave Borowitz 35f094b57b Add Tree and TreeEntry classes, with tests.
Change-Id: Idadd5fc59b85506260a1f57b5e7488aed590bfa1
2010-11-12 13:22:08 -08:00

976 lines
33 KiB
C

/*
* 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);
}