J. David Ibáñez 6f2b864619 Change API to create Git objects
Do not allow to create commits, trees, blobs and tags directly from the
constructor. For instance, now calling "Commit(...)" raises an error.
Instead use the create methods of the repository object:

  Before                         Now
  -----------------------------  -----------------------------
  commit = Commit(repo, ...)     sha = repo.create_commit(...)
  tag = Tag(repo, ...)           sha = repo.create_tag(...)

Most often you won't need to get the object just created, but if you
do just call "repo[sha]" afterwards. (Methods to create blobs and trees
are still missing, just like before.)

Similarly the method that creates a tree object from the index file does
not return the tree object anymore, but just its SHA:

  Before                         Now
  -----------------------------  -----------------------------
  tree = index.create_tree()     sha = index.create_tree()
2011-04-11 18:44:49 +02:00

1836 lines
60 KiB
C

/*
* Copyright 2010 Google, Inc.
* Copyright 2011 Itaapy
*
* 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 <git2.h>
typedef struct {
PyObject_HEAD
git_repository *repo;
PyObject *index; /* It will be None for a bare repository */
} Repository;
/* The structs for some of the 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;\
_ptr_type *_ptr_name;\
} _name;
OBJECT_STRUCT(Object, git_object, obj)
OBJECT_STRUCT(Commit, git_commit, commit)
OBJECT_STRUCT(Tree, git_tree, tree)
OBJECT_STRUCT(Blob, git_blob, blob)
typedef struct {
PyObject_HEAD
Repository *repo;
git_tag *tag;
PyObject *target;
} Tag;
typedef struct {
PyObject_HEAD
const git_tree_entry *entry;
Tree *tree;
} TreeEntry;
typedef struct {
PyObject_HEAD
Repository *repo;
git_index *index;
int own_obj:1;
} Index;
typedef struct {
PyObject_HEAD
git_index_entry *entry;
} IndexEntry;
typedef struct {
PyObject_HEAD
Repository *repo;
git_revwalk *walk;
} Walker;
static PyTypeObject RepositoryType;
static PyTypeObject ObjectType;
static PyTypeObject CommitType;
static PyTypeObject TreeEntryType;
static PyTypeObject TreeType;
static PyTypeObject BlobType;
static PyTypeObject TagType;
static PyTypeObject IndexType;
static PyTypeObject IndexEntryType;
static PyTypeObject WalkerType;
static PyObject *GitError;
static PyObject *
Error_type(int err) {
switch (err) {
case GIT_ENOTFOUND:
return PyExc_KeyError;
case GIT_EOSERR:
return PyExc_OSError;
case GIT_ENOTOID:
return PyExc_ValueError;
case GIT_ENOMEM:
return PyExc_MemoryError;
case GIT_EREVWALKOVER:
return PyExc_StopIteration;
default:
return GitError;
}
}
static PyObject *
Error_set(int err) {
assert(err < 0);
if (err == GIT_ENOTFOUND) {
/* KeyError expects the arg to be the missing key. If the caller called
* this instead of Error_set_py_obj, it means we don't know the key, but
* nor should we use git_strerror. */
PyErr_SetNone(PyExc_KeyError);
return NULL;
} else if (err == GIT_EOSERR) {
PyErr_SetFromErrno(GitError);
return NULL;
}
PyErr_SetString(Error_type(err), git_strerror(err));
return NULL;
}
static PyObject *
Error_set_str(int err, const char *str) {
if (err == GIT_ENOTFOUND) {
/* KeyError expects the arg to be the missing key. */
PyErr_Format(PyExc_KeyError, "%s", str);
return NULL;
}
PyErr_Format(Error_type(err), "%s: %s", str, git_strerror(err));
return NULL;
}
static PyObject *
Error_set_py_obj(int err, PyObject *py_obj) {
PyObject *py_str;
char *str;
assert(err < 0);
if (err == GIT_ENOTOID && !PyString_Check(py_obj)) {
PyErr_Format(PyExc_TypeError, "Git object id must be str, not %.200s",
py_obj->ob_type->tp_name);
return NULL;
} else if (err == GIT_ENOTFOUND) {
/* KeyError expects the arg to be the missing key. */
PyErr_SetObject(PyExc_KeyError, py_obj);
return NULL;
}
py_str = PyObject_Str(py_obj);
str = py_str ? PyString_AS_STRING(py_str) : "<error in __str__>";
PyErr_Format(Error_type(err), "%s: %s", str, git_strerror(err));
Py_XDECREF(py_str);
return NULL;
}
static int
py_str_to_git_oid(PyObject *py_str, git_oid *oid) {
char *hex;
int err;
hex = PyString_AsString(py_str);
if (hex == NULL) {
Error_set_py_obj(GIT_ENOTOID, py_str);
return 0;
}
err = git_oid_mkstr(oid, hex);
if (err < 0) {
Error_set_py_obj(err, py_str);
return 0;
}
return 1;
}
static int
Repository_init(Repository *self, PyObject *args, PyObject *kwds) {
char *path;
int err;
if (kwds) {
PyErr_SetString(PyExc_TypeError,
"Repository takes no keyword arugments");
return -1;
}
if (!PyArg_ParseTuple(args, "s", &path))
return -1;
err = git_repository_open(&self->repo, path);
if (err < 0) {
Error_set_str(err, path);
return -1;
}
return 0;
}
static void
Repository_dealloc(Repository *self) {
if (self->repo)
git_repository_free(self->repo);
Py_XDECREF(self->index);
self->ob_type->tp_free((PyObject*)self);
}
static int
Repository_contains(Repository *self, PyObject *value) {
git_oid oid;
if (!py_str_to_git_oid(value, &oid))
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*)BlobType.tp_alloc(&BlobType, 0);
break;
case GIT_OBJ_TAG:
py_obj = (Object*)TagType.tp_alloc(&TagType, 0);
break;
default:
assert(0);
}
if (!py_obj)
return (Object*)PyErr_NoMemory();
py_obj->obj = obj;
py_obj->repo = repo;
Py_INCREF(repo);
return py_obj;
}
static PyObject *
Repository_getitem(Repository *self, PyObject *value) {
git_oid oid;
int err;
git_object *obj;
Object *py_obj;
if (!py_str_to_git_oid(value, &oid))
return NULL;
err = git_object_lookup(&obj, self->repo, &oid, GIT_OBJ_ANY);
if (err < 0)
return Error_set_py_obj(err, value);
py_obj = wrap_object(obj, self);
if (!py_obj)
return NULL;
return (PyObject*)py_obj;
}
static int
Repository_read_raw(git_odb_object **obj, git_repository *repo, const git_oid *oid) {
return git_odb_read(obj, git_repository_database(repo), oid);
}
static PyObject *
Repository_read(Repository *self, PyObject *py_hex) {
git_oid oid;
int err;
git_odb_object *obj;
if (!py_str_to_git_oid(py_hex, &oid))
return NULL;
err = Repository_read_raw(&obj, self->repo, &oid);
if (err < 0)
return Error_set_py_obj(err, py_hex);
return Py_BuildValue(
"(ns#)",
git_odb_object_type(obj),
git_odb_object_data(obj),
git_odb_object_size(obj));
}
static PyObject *
Repository_get_index(Repository *self, void *closure) {
int err;
git_index *index;
Index *py_index;
assert(self->repo);
if (self->index == NULL) {
err = git_repository_index(&index, self->repo);
if (err == GIT_SUCCESS) {
py_index = (Index*)IndexType.tp_alloc(&IndexType, 0);
if (!py_index)
return PyErr_NoMemory();
py_index->repo = self;
py_index->index = index;
py_index->own_obj = 0;
self->index = (PyObject*)py_index;
} else if (err == GIT_EBAREINDEX) {
Py_INCREF(Py_None);
self->index = Py_None;
} else {
return Error_set(err);
}
}
Py_INCREF(self->index);
return self->index;
}
static PyObject *
Repository_walk(Repository *self, PyObject *args)
{
PyObject *value;
unsigned int sort;
int err;
git_oid oid;
git_revwalk *walk;
Walker *py_walker;
if (!PyArg_ParseTuple(args, "OI", &value, &sort))
return NULL;
if (value != Py_None && !PyString_Check(value)) {
PyErr_SetObject(PyExc_TypeError, value);
return NULL;
}
err = git_revwalk_new(&walk, self->repo);
if (err < 0)
return Error_set(err);
/* Sort */
git_revwalk_sorting(walk, sort);
/* Push */
if (value != Py_None) {
if (!py_str_to_git_oid(value, &oid)) {
git_revwalk_free(walk);
return NULL;
}
err = git_revwalk_push(walk, &oid);
if (err < 0) {
git_revwalk_free(walk);
return Error_set(err);
}
}
py_walker = PyObject_New(Walker, &WalkerType);
if (!py_walker) {
git_revwalk_free(walk);
return NULL;
}
Py_INCREF(self);
py_walker->repo = self;
py_walker->walk = walk;
return (PyObject*)py_walker;
}
static PyObject *
build_person(const git_signature *signature) {
return Py_BuildValue("(ssLi)", signature->name, signature->email,
signature->when.time, signature->when.offset);
}
static int
signature_converter(PyObject *value, git_signature **out) {
char *name, *email;
long long time;
int offset;
git_signature *signature;
if (!PyArg_ParseTuple(value, "ssLi", &name, &email, &time, &offset))
return 0;
signature = git_signature_new(name, email, time, offset);
if (signature == NULL) {
PyErr_SetNone(PyExc_MemoryError);
return 0;
}
*out = signature;
return 1;
}
static PyObject *
free_parents(git_oid **parents, int n) {
int i;
for (i = 0; i < n; i++)
free(parents[i]);
free(parents);
return NULL;
}
static PyObject *
Repository_create_commit(Repository *self, PyObject *args) {
git_signature *author, *committer;
char *message;
git_oid tree_oid, oid;
PyObject *py_parents, *py_parent;
int parent_count;
git_oid **parents;
int err, i;
char hex[GIT_OID_HEXSZ];
if (!PyArg_ParseTuple(args, "O&O&sO&O!",
signature_converter, &author,
signature_converter, &committer,
&message,
py_str_to_git_oid, &tree_oid,
&PyList_Type, &py_parents))
return NULL;
parent_count = (int)PyList_Size(py_parents);
parents = malloc(parent_count * sizeof(git_oid*));
if (parents == NULL) {
PyErr_SetNone(PyExc_MemoryError);
return NULL;
}
for (i = 0; i < parent_count; i++) {
parents[i] = malloc(sizeof(git_oid));
if (parents[i] == NULL) {
PyErr_SetNone(PyExc_MemoryError);
return free_parents(parents, i);
}
py_parent = PyList_GET_ITEM(py_parents, i);
if (!py_str_to_git_oid(py_parent, parents[i]))
return free_parents(parents, i);
}
err = git_commit_create(&oid, self->repo, NULL,
author, committer, message, &tree_oid,
parent_count, (const git_oid**)parents);
free_parents(parents, parent_count);
if (err < 0)
return Error_set(err);
git_oid_fmt(hex, &oid);
return PyString_FromStringAndSize(hex, GIT_OID_HEXSZ);
}
static PyObject *
Repository_create_tag(Repository *self, PyObject *args) {
char *tag_name, *message;
git_signature *tagger;
git_oid target, oid;
int err, target_type;
char hex[GIT_OID_HEXSZ];
if (!PyArg_ParseTuple(args, "sO&iO&s",
&tag_name,
py_str_to_git_oid, &target,
&target_type,
signature_converter, &tagger,
&message))
return NULL;
err = git_tag_create(&oid, self->repo,
tag_name, &target, target_type, tagger, message);
if (err < 0)
return NULL;
git_oid_fmt(hex, &oid);
return PyString_FromStringAndSize(hex, GIT_OID_HEXSZ);
}
static PyMethodDef Repository_methods[] = {
{"create_commit", (PyCFunction)Repository_create_commit, METH_VARARGS,
"Create a new commit object, return its SHA."},
{"create_tag", (PyCFunction)Repository_create_tag, METH_VARARGS,
"Create a new tag object, return its SHA."},
{"walk", (PyCFunction)Repository_walk, METH_VARARGS,
"Generator that traverses the history starting from the given commit."},
{"read", (PyCFunction)Repository_read, METH_O,
"Read raw object data from the repository."},
{NULL}
};
static PyGetSetDef Repository_getseters[] = {
{"index", (getter)Repository_get_index, NULL, "index file. ", NULL},
{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 */
Repository_getseters, /* 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)
{
git_object_close(self->obj);
Py_XDECREF(self->repo);
self->ob_type->tp_free((PyObject*)self);
}
static PyObject *
Object_get_type(Object *self) {
return PyInt_FromLong(git_object_type(self->obj));
}
static PyObject *
Object_get_sha(Object *self) {
const git_oid *id;
char hex[GIT_OID_HEXSZ];
id = git_object_id(self->obj);
if (!id)
Py_RETURN_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_odb_object *obj;
int err;
PyObject *result = NULL, *py_sha = NULL;
id = git_object_id(self->obj);
if (!id)
Py_RETURN_NONE; /* in-memory object */
err = Repository_read_raw(&obj, self->repo->repo, id);
if (err < 0) {
py_sha = Object_get_sha(self);
Error_set_py_obj(err, py_sha);
goto cleanup;
}
result = PyString_FromStringAndSize(
git_odb_object_data(obj),
git_odb_object_size(obj));
cleanup:
Py_XDECREF(py_sha);
return result;
}
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."},
{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 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 PyObject *
Commit_get_commit_time(Commit *commit) {
return PyLong_FromLong(git_commit_time(commit->commit));
}
static PyObject *
Commit_get_committer(Commit *commit) {
const git_signature *signature = git_commit_committer(commit->commit);
return build_person(signature);
}
static PyObject *
Commit_get_author(Commit *commit) {
const git_signature *signature = git_commit_author(commit->commit);
return build_person(signature);
}
static PyObject *
Commit_get_tree(Commit *commit) {
git_tree *tree;
Tree *py_tree;
int err;
err = git_commit_tree(&tree, commit->commit);
if (err == GIT_ENOTFOUND)
Py_RETURN_NONE;
if (err < 0)
return Error_set(err);
py_tree = PyObject_New(Tree, &TreeType);
Py_INCREF(commit->repo);
py_tree->repo = commit->repo;
py_tree->tree = (git_tree*)tree;
return (PyObject*)py_tree;
}
static PyObject *
Commit_get_parents(Commit *commit)
{
unsigned int i, parent_count;
int err;
git_commit *parent;
PyObject *obj;
PyObject *list;
parent_count = git_commit_parentcount(commit->commit);
list = PyList_New(parent_count);
if (!list)
return NULL;
for (i=0; i < parent_count; i++) {
err = git_commit_parent(&parent, commit->commit, i);
if (err < 0) {
Py_DECREF(list);
Error_set(err);
return NULL;
}
obj = (PyObject*)wrap_object((git_object *)parent, commit->repo);
if (obj == NULL) {
Py_DECREF(list);
return NULL;
}
PyList_SET_ITEM(list, i, obj);
}
return list;
}
static PyGetSetDef Commit_getseters[] = {
{"message_short", (getter)Commit_get_message_short, NULL, "short message",
NULL},
{"message", (getter)Commit_get_message, NULL, "message", NULL},
{"commit_time", (getter)Commit_get_commit_time, NULL, "commit time",
NULL},
{"committer", (getter)Commit_get_committer, NULL, "committer", NULL},
{"author", (getter)Commit_get_author, NULL, "author", NULL},
{"tree", (getter)Commit_get_tree, NULL, "tree object", NULL},
{"parents", (getter)Commit_get_parents, NULL, "parents of this commit",
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 */
0, /* 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 PyObject *
TreeEntry_get_name(TreeEntry *self) {
return PyString_FromString(git_tree_entry_name(self->entry));
}
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 PyObject *
TreeEntry_to_object(TreeEntry *self) {
git_object *obj;
int err;
char hex[GIT_OID_HEXSZ + 1];
err = git_tree_entry_2object(&obj, self->tree->repo->repo, self->entry);
if (err < 0) {
git_oid_fmt(hex, git_tree_entry_id(self->entry));
hex[GIT_OID_HEXSZ] = '\0';
return Error_set_str(err, hex);
}
return (PyObject*)wrap_object(obj, self->tree->repo);
}
static PyGetSetDef TreeEntry_getseters[] = {
{"attributes", (getter)TreeEntry_get_attributes, NULL, "attributes", NULL},
{"name", (getter)TreeEntry_get_name, NULL, "name", NULL},
{"sha", (getter)TreeEntry_get_sha, NULL, "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 Py_ssize_t
Tree_len(Tree *self) {
assert(self->tree);
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);
if (name == NULL)
return -1;
return git_tree_entry_byname(self->tree, name) ? 1 : 0;
}
static TreeEntry *
wrap_tree_entry(const 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;
const 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;
const 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_Format(PyExc_TypeError,
"Tree entry index must be int or str, not %.200s",
value->ob_type->tp_name);
return 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 */
0, /* 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 */
0, /* 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 */
0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};
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 */
0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};
static void
Tag_dealloc(Tag *self) {
Py_XDECREF(self->target);
self->ob_type->tp_free((PyObject*)self);
}
static PyObject *
Tag_get_target(Tag *self) {
git_object *target;
int err;
if (self->target == NULL) {
err = git_tag_target(&target, self->tag);
if (err == GIT_ENOTFOUND) {
/* This can only happen if we have a new tag with no target set
* yet. */
Py_INCREF(Py_None);
self->target = Py_None;
} else if (err < 0)
return Error_set(err);
else
self->target = (PyObject*)wrap_object(target, self->repo);
}
Py_INCREF(self->target);
return self->target;
}
static PyObject *
Tag_get_name(Tag *self) {
const char *name;
name = git_tag_name(self->tag);
if (!name)
Py_RETURN_NONE;
return PyString_FromString(name);
}
static PyObject *
Tag_get_tagger(Tag *tag) {
const git_signature *signature = git_tag_tagger(tag->tag);
if (!signature)
Py_RETURN_NONE;
return build_person(signature);
}
static PyObject *
Tag_get_message(Tag *self) {
const char *message;
message = git_tag_message(self->tag);
if (!message)
Py_RETURN_NONE;
return PyString_FromString(message);
}
static PyGetSetDef Tag_getseters[] = {
{"target", (getter)Tag_get_target, NULL, "tagged object", NULL},
{"name", (getter)Tag_get_name, NULL, "tag name", NULL},
{"tagger", (getter)Tag_get_tagger, NULL, "tagger", NULL},
{"message", (getter)Tag_get_message, NULL, "tag message",
NULL},
{NULL}
};
static PyTypeObject TagType = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"pygit2.Tag", /*tp_name*/
sizeof(Tag), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)Tag_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*/
"Tag 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 */
Tag_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
Index_init(Index *self, PyObject *args, PyObject *kwds) {
char *path;
int err;
if (kwds) {
PyErr_SetString(PyExc_TypeError,
"Index takes no keyword arugments");
return -1;
}
if (!PyArg_ParseTuple(args, "s", &path))
return -1;
err = git_index_open_bare(&self->index, path);
if (err < 0) {
Error_set_str(err, path);
return -1;
}
self->own_obj = 1;
return 0;
}
static void
Index_dealloc(Index* self)
{
if (self->own_obj)
git_index_free(self->index);
Py_XDECREF(self->repo);
self->ob_type->tp_free((PyObject*)self);
}
static PyObject *
Index_add(Index *self, PyObject *args) {
int err;
const char *path;
int stage=0;
if (!PyArg_ParseTuple(args, "s|i", &path, &stage))
return NULL;
err = git_index_add(self->index, path, stage);
if (err < 0)
return Error_set_str(err, path);
Py_RETURN_NONE;
}
static PyObject *
Index_clear(Index *self) {
git_index_clear(self->index);
Py_RETURN_NONE;
}
static PyObject *
Index_find(Index *self, PyObject *py_path) {
char *path;
long idx;
path = PyString_AsString(py_path);
if (!path)
return NULL;
idx = (long)git_index_find(self->index, path);
if (idx < 0)
return Error_set_str(idx, path);
return PyInt_FromLong(idx);
}
static PyObject *
Index_read(Index *self) {
int err;
err = git_index_read(self->index);
if (err < GIT_SUCCESS)
return Error_set(err);
Py_RETURN_NONE;
}
static PyObject *
Index_write(Index *self) {
int err;
err = git_index_write(self->index);
if (err < GIT_SUCCESS)
return Error_set(err);
Py_RETURN_NONE;
}
/* This is an internal function, used by Index_getitem and Index_setitem */
static int
Index_get_position(Index *self, PyObject *value) {
char *path;
int idx;
if (PyString_Check(value)) {
path = PyString_AsString(value);
if (!path)
return -1;
idx = git_index_find(self->index, path);
if (idx < 0) {
Error_set_str(idx, path);
return -1;
}
} else if (PyInt_Check(value)) {
idx = (int)PyInt_AsLong(value);
if (idx == -1 && PyErr_Occurred())
return -1;
if (idx < 0) {
PyErr_SetObject(PyExc_ValueError, value);
return -1;
}
} else {
PyErr_Format(PyExc_TypeError,
"Index entry key must be int or str, not %.200s",
value->ob_type->tp_name);
return -1;
}
return idx;
}
static int
Index_contains(Index *self, PyObject *value) {
char *path;
int idx;
path = PyString_AsString(value);
if (!path)
return -1;
idx = git_index_find(self->index, path);
if (idx == GIT_ENOTFOUND)
return 0;
if (idx < 0) {
Error_set_str(idx, path);
return -1;
}
return 1;
}
static Py_ssize_t
Index_len(Index *self) {
return (Py_ssize_t)git_index_entrycount(self->index);
}
static PyObject *
Index_getitem(Index *self, PyObject *value) {
int idx;
git_index_entry *index_entry;
IndexEntry *py_index_entry;
idx = Index_get_position(self, value);
if (idx == -1)
return NULL;
index_entry = git_index_get(self->index, idx);
if (!index_entry) {
PyErr_SetObject(PyExc_KeyError, value);
return NULL;
}
py_index_entry = (IndexEntry*)IndexEntryType.tp_alloc(&IndexEntryType, 0);
if (!py_index_entry)
return PyErr_NoMemory();
py_index_entry->entry = index_entry;
Py_INCREF(py_index_entry);
return (PyObject*)py_index_entry;
}
static int
Index_setitem(Index *self, PyObject *key, PyObject *value) {
int err;
int idx;
if (value) {
PyErr_SetString(PyExc_NotImplementedError,
"set item on index not yet implemented");
return -1;
}
idx = Index_get_position(self, key);
if (idx == -1)
return -1;
err = git_index_remove(self->index, idx);
if (err < 0) {
Error_set(err);
return -1;
}
return 0;
}
static PyObject *
Index_create_tree(Index *self) {
git_oid oid;
int err;
char hex[GIT_OID_HEXSZ];
err = git_tree_create_fromindex(&oid, self->index);
if (err < 0)
return Error_set(err);
git_oid_fmt(hex, &oid);
return PyString_FromStringAndSize(hex, GIT_OID_HEXSZ);
}
static PyMethodDef Index_methods[] = {
{"add", (PyCFunction)Index_add, METH_VARARGS,
"Add or update an index entry from a file in disk."},
{"clear", (PyCFunction)Index_clear, METH_NOARGS,
"Clear the contents (all the entries) of an index object."},
{"_find", (PyCFunction)Index_find, METH_O,
"Find the first index of any entries which point to given path in the"
" Git index."},
{"read", (PyCFunction)Index_read, METH_NOARGS,
"Update the contents of an existing index object in memory by reading"
" from the hard disk."},
{"write", (PyCFunction)Index_write, METH_NOARGS,
"Write an existing index object from memory back to disk using an"
" atomic file lock."},
{"create_tree", (PyCFunction)Index_create_tree, METH_NOARGS,
"Create a tree from the index file, return its SHA."},
{NULL}
};
static PySequenceMethods Index_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)Index_contains, /* sq_contains */
};
static PyMappingMethods Index_as_mapping = {
(lenfunc)Index_len, /* mp_length */
(binaryfunc)Index_getitem, /* mp_subscript */
(objobjargproc)Index_setitem, /* mp_ass_subscript */
};
static PyTypeObject IndexType = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"pygit2.Index", /* tp_name */
sizeof(Index), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)Index_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
&Index_as_sequence, /* tp_as_sequence */
&Index_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 */
"Index file", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
Index_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)Index_init, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};
static void
IndexEntry_dealloc(IndexEntry *self) {
self->ob_type->tp_free((PyObject*)self);
}
static PyObject *
IndexEntry_get_path(IndexEntry *self) {
return PyString_FromString(self->entry->path);
}
static PyObject *
IndexEntry_get_sha(IndexEntry *self) {
char hex[GIT_OID_HEXSZ];
git_oid_fmt(hex, &self->entry->oid);
return PyString_FromStringAndSize(hex, GIT_OID_HEXSZ);
}
static PyGetSetDef IndexEntry_getseters[] = {
{"path", (getter)IndexEntry_get_path, NULL, "path", NULL},
{"sha", (getter)IndexEntry_get_sha, NULL, "hex SHA", NULL},
{NULL},
};
static PyTypeObject IndexEntryType = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"pygit2.IndexEntry", /* tp_name */
sizeof(IndexEntry), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)IndexEntry_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, /* tp_flags */
"Index entry", /* 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 */
IndexEntry_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 void
Walker_dealloc(Walker *self) {
git_revwalk_free(self->walk);
Py_DECREF(self->repo);
self->ob_type->tp_free((PyObject*)self);
}
static PyObject *
Walker_hide(Walker *self, PyObject *py_hex) {
int err;
git_oid oid;
if (!py_str_to_git_oid(py_hex, &oid))
return NULL;
err = git_revwalk_hide(self->walk, &oid);
if (err < 0)
return Error_set(err);
Py_RETURN_NONE;
}
static PyObject *
Walker_push(Walker *self, PyObject *py_hex) {
int err;
git_oid oid;
if (!py_str_to_git_oid(py_hex, &oid))
return NULL;
err = git_revwalk_push(self->walk, &oid);
if (err < 0)
return Error_set(err);
Py_RETURN_NONE;
}
static PyObject *
Walker_sort(Walker *self, PyObject *py_sort_mode) {
int sort_mode;
sort_mode = (int)PyInt_AsLong(py_sort_mode);
if (sort_mode == -1 && PyErr_Occurred())
return NULL;
git_revwalk_sorting(self->walk, sort_mode);
Py_RETURN_NONE;
}
static PyObject *
Walker_reset(Walker *self) {
git_revwalk_reset(self->walk);
Py_RETURN_NONE;
}
static PyObject *
Walker_iter(Walker *self) {
Py_INCREF(self);
return (PyObject*)self;
}
static PyObject *
Walker_iternext(Walker *self) {
int err;
git_commit *commit;
Commit *py_commit;
git_oid oid;
err = git_revwalk_next(&oid, self->walk);
if (err < 0)
return Error_set(err);
err = git_commit_lookup(&commit, self->repo->repo, &oid);
if (err < 0)
return Error_set(err);
py_commit = PyObject_New(Commit, &CommitType);
if (!py_commit)
return NULL;
py_commit->commit = commit;
Py_INCREF(self->repo);
py_commit->repo = self->repo;
return (PyObject*)py_commit;
}
static PyMethodDef Walker_methods[] = {
{"hide", (PyCFunction)Walker_hide, METH_O,
"Mark a commit (and its ancestors) uninteresting for the output."},
{"push", (PyCFunction)Walker_push, METH_O,
"Mark a commit to start traversal from."},
{"reset", (PyCFunction)Walker_reset, METH_NOARGS,
"Reset the walking machinery for reuse."},
{"sort", (PyCFunction)Walker_sort, METH_O,
"Change the sorting mode (this resets the walker)."},
{NULL}
};
static PyTypeObject WalkerType = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"pygit2.Walker", /* tp_name */
sizeof(Walker), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)Walker_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_HAVE_ITER, /* tp_flags */
"Revision walker", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
(getiterfunc)Walker_iter, /* tp_iter */
(iternextfunc)Walker_iternext, /* tp_iternext */
Walker_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 */
0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};
static PyObject *
init_repository(PyObject *self, PyObject *args) {
git_repository *repo;
Repository *py_repo;
const char *path;
unsigned int bare;
int err;
if (!PyArg_ParseTuple(args, "sI", &path, &bare))
return NULL;
err = git_repository_init(&repo, path, bare);
if (err < 0) {
Error_set_str(err, path);
return NULL;
}
py_repo = PyObject_New(Repository, &RepositoryType);
if (!py_repo) {
git_repository_free(repo);
return NULL;
}
py_repo->repo = repo;
py_repo->index = NULL;
return (PyObject*)py_repo;
};
static PyMethodDef module_methods[] = {
{"init_repository", init_repository, METH_VARARGS,
"Creates a new Git repository in the given folder."},
{NULL}
};
PyMODINIT_FUNC
initpygit2(void)
{
PyObject* m;
GitError = PyErr_NewException("pygit2.GitError", NULL, NULL);
RepositoryType.tp_new = PyType_GenericNew;
if (PyType_Ready(&RepositoryType) < 0)
return;
/* Do not set 'tp_new' for Git objects. To create Git objects use the
* Repository.create_XXX methods */
if (PyType_Ready(&ObjectType) < 0)
return;
CommitType.tp_base = &ObjectType;
if (PyType_Ready(&CommitType) < 0)
return;
TreeType.tp_base = &ObjectType;
if (PyType_Ready(&TreeType) < 0)
return;
BlobType.tp_base = &ObjectType;
if (PyType_Ready(&BlobType) < 0)
return;
TagType.tp_base = &ObjectType;
if (PyType_Ready(&TagType) < 0)
return;
TreeEntryType.tp_new = PyType_GenericNew;
if (PyType_Ready(&TreeEntryType) < 0)
return;
IndexType.tp_new = PyType_GenericNew;
if (PyType_Ready(&IndexType) < 0)
return;
IndexEntryType.tp_new = PyType_GenericNew;
if (PyType_Ready(&IndexEntryType) < 0)
return;
WalkerType.tp_new = PyType_GenericNew;
if (PyType_Ready(&WalkerType) < 0)
return;
m = Py_InitModule3("pygit2", module_methods,
"Python bindings for libgit2.");
if (m == NULL)
return;
Py_INCREF(GitError);
PyModule_AddObject(m, "GitError", GitError);
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);
Py_INCREF(&BlobType);
PyModule_AddObject(m, "Blob", (PyObject *)&BlobType);
Py_INCREF(&TagType);
PyModule_AddObject(m, "Tag", (PyObject *)&TagType);
Py_INCREF(&IndexType);
PyModule_AddObject(m, "Index", (PyObject *)&IndexType);
Py_INCREF(&IndexEntryType);
PyModule_AddObject(m, "IndexEntry", (PyObject *)&IndexEntryType);
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);
PyModule_AddIntConstant(m, "GIT_SORT_NONE", GIT_SORT_NONE);
PyModule_AddIntConstant(m, "GIT_SORT_TOPOLOGICAL", GIT_SORT_TOPOLOGICAL);
PyModule_AddIntConstant(m, "GIT_SORT_TIME", GIT_SORT_TIME);
PyModule_AddIntConstant(m, "GIT_SORT_REVERSE", GIT_SORT_REVERSE);
}