/* * 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. */ #define PY_SSIZE_T_CLEAN #include <Python.h> #include <osdefs.h> #include <git2.h> /* Python 3 support */ #if PY_MAJOR_VERSION >= 3 #define PyInt_AsLong PyLong_AsLong #define PyInt_Check PyLong_Check #define PyInt_FromLong PyLong_FromLong #define PyString_AS_STRING PyBytes_AS_STRING #define PyString_AsString PyBytes_AsString #define PyString_AsStringAndSize PyBytes_AsStringAndSize #define PyString_Check PyBytes_Check #define PyString_FromString PyBytes_FromString #define PyString_FromStringAndSize PyBytes_FromStringAndSize #define PyString_Size PyBytes_Size #endif /* Utilities */ Py_LOCAL_INLINE(PyObject*) to_unicode(const char *value, const char *encoding, const char *errors) { if (encoding == NULL) encoding = "utf-8"; return PyUnicode_Decode(value, strlen(value), encoding, errors); } Py_LOCAL_INLINE(PyObject*) to_bytes(const char * value) { return PyString_FromString(value); } #if PY_MAJOR_VERSION == 2 #define to_path(x) to_bytes(x) #define to_encoding(x) to_bytes(x) #else #define to_path(x) to_unicode(x, Py_FileSystemDefaultEncoding, "strict") #define to_encoding(x) PyUnicode_DecodeASCII(x, strlen(x), "strict") #endif #define CHECK_REFERENCE(self)\ if (self->reference == NULL) {\ PyErr_SetString(GitError, "deleted reference");\ return NULL;\ } #define CHECK_REFERENCE_INT(self)\ if (self->reference == NULL) {\ PyErr_SetString(GitError, "deleted reference");\ return -1;\ } /* Python objects */ 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(TreeBuilder, git_treebuilder, bld) OBJECT_STRUCT(Blob, git_blob, blob) OBJECT_STRUCT(Tag, git_tag, tag) OBJECT_STRUCT(Index, git_index, index) OBJECT_STRUCT(Walker, git_revwalk, walk) typedef struct { PyObject_HEAD const git_tree_entry *entry; } TreeEntry; typedef struct { PyObject_HEAD Tree *owner; int i; } TreeIter; typedef struct { PyObject_HEAD git_index_entry *entry; } IndexEntry; typedef struct { PyObject_HEAD Index *owner; int i; } IndexIter; typedef struct { PyObject_HEAD git_reference *reference; } Reference; typedef struct { PyObject_HEAD Object *obj; const git_signature *signature; const char *encoding; } Signature; static PyTypeObject RepositoryType; static PyTypeObject ObjectType; static PyTypeObject CommitType; static PyTypeObject TreeType; static PyTypeObject TreeBuilderType; static PyTypeObject TreeEntryType; static PyTypeObject TreeIterType; static PyTypeObject BlobType; static PyTypeObject TagType; static PyTypeObject IndexType; static PyTypeObject IndexEntryType; static PyTypeObject IndexIterType; static PyTypeObject WalkerType; static PyTypeObject ReferenceType; static PyTypeObject SignatureType; 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; } } /* * Python doesn't like it when the error string is NULL. Not giving * back an error string could be a bug in the library */ static const char * git_last_error(void) { const char *ret; ret = git_lasterror(); return ret != NULL ? ret : "(No error information given)"; } static PyObject * Error_set(int err) { assert(err < 0); if (err == GIT_EOSERR) return PyErr_SetFromErrno(GitError); PyErr_SetString(Error_type(err), git_last_error()); 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_SetString(PyExc_KeyError, str); return NULL; } return PyErr_Format(Error_type(err), "%s: %s", str, git_last_error()); } static PyObject * Error_set_oid(int err, const git_oid *oid, size_t len) { char hex[GIT_OID_HEXSZ + 1]; git_oid_fmt(hex, oid); hex[len] = '\0'; return Error_set_str(err, hex); } static PyObject * lookup_object_prefix(Repository *repo, const git_oid *oid, size_t len, git_otype type) { int err; git_object *obj; Object *py_obj = NULL; err = git_object_lookup_prefix(&obj, repo->repo, oid, (unsigned int)len, type); if (err < 0) return Error_set_oid(err, oid, len); switch (git_object_type(obj)) { case GIT_OBJ_COMMIT: py_obj = PyObject_New(Object, &CommitType); break; case GIT_OBJ_TREE: py_obj = PyObject_New(Object, &TreeType); break; case GIT_OBJ_BLOB: py_obj = PyObject_New(Object, &BlobType); break; case GIT_OBJ_TAG: py_obj = PyObject_New(Object, &TagType); break; default: assert(0); } if (py_obj) { py_obj->obj = obj; py_obj->repo = repo; Py_INCREF(repo); } return (PyObject*)py_obj; } static PyObject * lookup_object(Repository *repo, const git_oid *oid, git_otype type) { return lookup_object_prefix(repo, oid, GIT_OID_HEXSZ, type); } static git_otype int_to_loose_object_type(int type_id) { switch((git_otype)type_id) { case GIT_OBJ_COMMIT: return GIT_OBJ_COMMIT; case GIT_OBJ_TREE: return GIT_OBJ_TREE; case GIT_OBJ_BLOB: return GIT_OBJ_BLOB; case GIT_OBJ_TAG: return GIT_OBJ_TAG; default: return GIT_OBJ_BAD; } } static PyObject * wrap_reference(git_reference * c_reference) { Reference *py_reference=NULL; py_reference = PyObject_New(Reference, &ReferenceType); if (py_reference) py_reference->reference = c_reference; return (PyObject *)py_reference; } static size_t py_str_to_git_oid(PyObject *py_str, git_oid *oid) { PyObject *py_hex; char *hex_or_bin; int err; Py_ssize_t len; /* Case 1: raw sha */ if (PyString_Check(py_str)) { hex_or_bin = PyString_AsString(py_str); if (hex_or_bin == NULL) return 0; git_oid_fromraw(oid, (const unsigned char*)hex_or_bin); return GIT_OID_HEXSZ; } /* Case 2: hex sha */ if (PyUnicode_Check(py_str)) { py_hex = PyUnicode_AsASCIIString(py_str); if (py_hex == NULL) return 0; err = PyString_AsStringAndSize(py_hex, &hex_or_bin, &len); Py_DECREF(py_hex); if (err) return 0; err = git_oid_fromstrn(oid, hex_or_bin, len); if (err < 0) { PyErr_SetObject(Error_type(err), py_str); return 0; } return len; } /* Type error */ PyErr_Format(PyExc_TypeError, "Git object id must be byte or a text string, not: %.200s", Py_TYPE(py_str)->tp_name); return 0; } #define TODO_SUPPORT_SHORT_HEXS(len) \ if (0 < len && len < GIT_OID_HEXSZ) {\ PyErr_SetString(PyExc_NotImplementedError,\ "short strings not yet supported");\ len = 0;\ } #define git_oid_to_python(id) \ PyString_FromStringAndSize((const char*)id, GIT_OID_RAWSZ) static PyObject * git_oid_to_py_str(const git_oid *oid) { char hex[GIT_OID_HEXSZ]; git_oid_fmt(hex, oid); return PyUnicode_DecodeASCII(hex, GIT_OID_HEXSZ, "strict"); } char * py_str_to_c_str(PyObject *value, const char *encoding) { char *c_str; /* Case 1: byte string */ if (PyString_Check(value)) return PyString_AsString(value); /* Case 2: text string */ if (PyUnicode_Check(value)) { if (encoding == NULL) value = PyUnicode_AsUTF8String(value); else value = PyUnicode_AsEncodedString(value, encoding, "strict"); if (value == NULL) return NULL; c_str = PyString_AsString(value); Py_DECREF(value); return c_str; } /* Type error */ PyErr_Format(PyExc_TypeError, "unexpected %.200s", Py_TYPE(value)->tp_name); return NULL; } #define py_path_to_c_str(py_path) \ py_str_to_c_str(py_path, Py_FileSystemDefaultEncoding) static int Repository_init(Repository *self, PyObject *args, PyObject *kwds) { char *path; int err; if (kwds) { PyErr_SetString(PyExc_TypeError, "Repository takes no keyword arguments"); 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) { PyObject_GC_UnTrack(self); Py_XDECREF(self->index); git_repository_free(self->repo); PyObject_GC_Del(self); } static int Repository_traverse(Repository *self, visitproc visit, void *arg) { Py_VISIT(self->index); return 0; } static int Repository_clear(Repository *self) { Py_CLEAR(self->index); return 0; } static int Repository_contains(Repository *self, PyObject *value) { git_oid oid; git_odb *odb; size_t len; int err, exists; len = py_str_to_git_oid(value, &oid); TODO_SUPPORT_SHORT_HEXS(len) if (len == 0) return -1; err = git_repository_odb(&odb, self->repo); if (err < 0) { Error_set(err); return -1; } exists = git_odb_exists(odb, &oid); git_odb_free(odb); return exists; } static PyObject * Repository_getitem(Repository *self, PyObject *value) { git_oid oid; size_t len; len = py_str_to_git_oid(value, &oid); if (len == 0) return NULL; return lookup_object_prefix(self, &oid, len, GIT_OBJ_ANY); } static git_odb_object * Repository_read_raw(git_repository *repo, const git_oid *oid, size_t len) { git_odb *odb; git_odb_object *obj; int err; err = git_repository_odb(&odb, repo); if (err < 0) { Error_set(err); return NULL; } err = git_odb_read_prefix(&obj, odb, oid, (unsigned int)len); git_odb_free(odb); if (err < 0) { Error_set_oid(err, oid, len); return NULL; } return obj; } static PyObject * Repository_read(Repository *self, PyObject *py_hex) { git_oid oid; git_odb_object *obj; size_t len; PyObject* tuple; len = py_str_to_git_oid(py_hex, &oid); if (len == 0) return NULL; obj = Repository_read_raw(self->repo, &oid, len); if (obj == NULL) return NULL; tuple = Py_BuildValue( "(ns#)", git_odb_object_type(obj), git_odb_object_data(obj), git_odb_object_size(obj)); git_odb_object_free(obj); return tuple; } static PyObject * Repository_write(Repository *self, PyObject *args) { int err; git_oid oid; git_odb *odb; git_odb_stream* stream; int type_id; const char* buffer; Py_ssize_t buflen; git_otype type; if (!PyArg_ParseTuple(args, "Is#", &type_id, &buffer, &buflen)) return NULL; type = int_to_loose_object_type(type_id); if (type == GIT_OBJ_BAD) return PyErr_Format(PyExc_ValueError, "%d", type_id); err = git_repository_odb(&odb, self->repo); if (err < 0) return Error_set(err); err = git_odb_open_wstream(&stream, odb, buflen, type); git_odb_free(odb); if (err < 0) return Error_set(err); stream->write(stream, buffer, buflen); err = stream->finalize_write(&oid, stream); stream->free(stream); return git_oid_to_python(oid.id); } 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 < 0) return Error_set(err); py_index = PyObject_GC_New(Index, &IndexType); if (!py_index) { git_index_free(index); return NULL; } Py_INCREF(self); py_index->repo = self; py_index->index = index; PyObject_GC_Track(py_index); self->index = (PyObject*)py_index; } Py_INCREF(self->index); return self->index; } static PyObject * Repository_get_path(Repository *self, void *closure) { return to_path(git_repository_path(self->repo)); } static PyObject * Repository_get_workdir(Repository *self, void *closure) { const char *c_path; c_path = git_repository_workdir(self->repo); if (c_path == NULL) Py_RETURN_NONE; return to_path(c_path); } static PyObject * Repository_walk(Repository *self, PyObject *args) { PyObject *value; unsigned int sort; int err; git_oid oid; git_revwalk *walk; Walker *py_walker; size_t len; if (!PyArg_ParseTuple(args, "OI", &value, &sort)) 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) { len = py_str_to_git_oid(value, &oid); TODO_SUPPORT_SHORT_HEXS(len) if (len == 0) { 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_signature(Object *obj, const git_signature *signature, const char *encoding) { Signature *py_signature; py_signature = PyObject_New(Signature, &SignatureType); if (py_signature) { Py_INCREF(obj); py_signature->obj = obj; py_signature->signature = signature; py_signature->encoding = encoding; } return (PyObject*)py_signature; } static PyObject * Repository_create_commit(Repository *self, PyObject *args) { Signature *py_author, *py_committer; PyObject *py_oid, *py_message, *py_parents, *py_parent; PyObject *py_result = NULL; char *message, *update_ref, *encoding = NULL; git_oid oid; git_tree *tree = NULL; int parent_count; git_commit **parents = NULL; int err = 0, i = 0; size_t len; if (!PyArg_ParseTuple(args, "zO!O!OOO!|s", &update_ref, &SignatureType, &py_author, &SignatureType, &py_committer, &py_message, &py_oid, &PyList_Type, &py_parents, &encoding)) return NULL; len = py_str_to_git_oid(py_oid, &oid); if (len == 0) goto out; message = py_str_to_c_str(py_message, encoding); err = git_tree_lookup_prefix(&tree, self->repo, &oid, (unsigned int)len); if (err < 0) { Error_set(err); goto out; } parent_count = (int)PyList_Size(py_parents); parents = malloc(parent_count * sizeof(git_commit*)); if (parents == NULL) { PyErr_SetNone(PyExc_MemoryError); goto out; } for (; i < parent_count; i++) { py_parent = PyList_GET_ITEM(py_parents, i); len = py_str_to_git_oid(py_parent, &oid); if (len == 0) goto out; if (git_commit_lookup_prefix(&parents[i], self->repo, &oid, (unsigned int)len)) goto out; } err = git_commit_create(&oid, self->repo, update_ref, py_author->signature, py_committer->signature, encoding, message, tree, parent_count, (const git_commit**)parents); if (err < 0) { Error_set(err); goto out; } py_result = git_oid_to_python(oid.id); out: git_tree_free(tree); while (i > 0) { i--; git_commit_free(parents[i]); } free(parents); return py_result; } static PyObject * Repository_create_tag(Repository *self, PyObject *args) { PyObject *py_oid; Signature *py_tagger; char *tag_name, *message; git_oid oid; git_object *target = NULL; int err, target_type; size_t len; if (!PyArg_ParseTuple(args, "sOiO!s", &tag_name, &py_oid, &target_type, &SignatureType, &py_tagger, &message)) return NULL; len = py_str_to_git_oid(py_oid, &oid); if (len == 0) return NULL; err = git_object_lookup_prefix(&target, self->repo, &oid, (unsigned int)len, target_type); err = err < 0 ? err : git_tag_create(&oid, self->repo, tag_name, target, py_tagger->signature, message, 0); git_object_free(target); if (err < 0) return Error_set_oid(err, &oid, len); return git_oid_to_python(oid.id); } static PyObject * Repository_listall_references(Repository *self, PyObject *args) { unsigned list_flags=GIT_REF_LISTALL; git_strarray c_result; PyObject *py_result, *py_string; unsigned index; int err; /* 1- Get list_flags */ if (!PyArg_ParseTuple(args, "|I", &list_flags)) return NULL; /* 2- Get the C result */ err = git_reference_listall(&c_result, self->repo, list_flags); if (err < 0) return Error_set(err); /* 3- Create a new PyTuple */ py_result = PyTuple_New(c_result.count); if (py_result == NULL) goto out; /* 4- Fill it */ for (index=0; index < c_result.count; index++) { py_string = to_path((c_result.strings)[index]); if (py_string == NULL) { Py_CLEAR(py_result); goto out; } PyTuple_SET_ITEM(py_result, index, py_string); } out: git_strarray_free(&c_result); return py_result; } static PyObject * Repository_lookup_reference(Repository *self, PyObject *py_name) { git_reference *c_reference; char *c_name; int err; /* 1- Get the C name */ c_name = py_path_to_c_str(py_name); if (c_name == NULL) return NULL; /* 2- Lookup */ err = git_reference_lookup(&c_reference, self->repo, c_name); if (err < 0) return Error_set_str(err, c_name); /* 3- Make an instance of Reference and return it */ return wrap_reference(c_reference); } static PyObject * Repository_create_reference(Repository *self, PyObject *args) { PyObject *py_oid; git_reference *c_reference; char *c_name; git_oid oid; int err; size_t len; /* 1- Get the C variables */ if (!PyArg_ParseTuple(args, "sO", &c_name, &py_oid)) return NULL; len = py_str_to_git_oid(py_oid, &oid); TODO_SUPPORT_SHORT_HEXS(len) if (len == 0) return NULL; /* 2- Create the reference */ err = git_reference_create_oid(&c_reference, self->repo, c_name, &oid, 0); if (err < 0) return Error_set(err); /* 3- Make an instance of Reference and return it */ return wrap_reference(c_reference); } static PyObject * Repository_create_symbolic_reference(Repository *self, PyObject *args) { git_reference *c_reference; char *c_name, *c_target; int err; /* 1- Get the C variables */ if (!PyArg_ParseTuple(args, "ss", &c_name, &c_target)) return NULL; /* 2- Create the reference */ err = git_reference_create_symbolic(&c_reference, self->repo, c_name, c_target, 0); if (err < 0) return Error_set(err); /* 3- Make an instance of Reference and return it */ return wrap_reference(c_reference); } static PyObject * Repository_packall_references(Repository *self, PyObject *args) { int err; /* 1- Pack */ err = git_reference_packall(self->repo); if (err < 0) return Error_set(err); /* 2- Return None */ Py_RETURN_NONE; } static int read_status_cb(const char *path, unsigned int status_flags, void *payload) { /* This is the callback that will be called in git_status_foreach. It * will be called for every path.*/ PyObject *flags; flags = PyInt_FromLong((long) status_flags); PyDict_SetItemString(payload, path, flags); return GIT_SUCCESS; } static PyObject * Repository_status(Repository *self, PyObject *args) { PyObject *payload_dict; payload_dict = PyDict_New(); git_status_foreach(self->repo, read_status_cb, payload_dict); return payload_dict; } static PyObject * Repository_status_file(Repository *self, PyObject *value) { char *path; unsigned int status; int err; path = py_path_to_c_str(value); if (!path) return NULL; err = git_status_file(&status, self->repo, path); if (err < 0) return Error_set_str(err, path); return PyInt_FromLong(status); } 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."}, {"write", (PyCFunction)Repository_write, METH_VARARGS, "Write raw object data into the repository. First arg is the object\n" "type, the second one a buffer with data. Return the object id (sha)\n" "of the created object."}, {"listall_references", (PyCFunction)Repository_listall_references, METH_VARARGS, "Return a list with all the references in the repository."}, {"lookup_reference", (PyCFunction)Repository_lookup_reference, METH_O, "Lookup a reference by its name in a repository."}, {"create_reference", (PyCFunction)Repository_create_reference, METH_VARARGS, "Create a new reference \"name\" that points to the object given by its " "\"sha\"."}, {"create_symbolic_reference", (PyCFunction)Repository_create_symbolic_reference, METH_VARARGS, "Create a new symbolic reference \"name\" that points to the reference\n" "\"target\"."}, {"packall_references", (PyCFunction)Repository_packall_references, METH_NOARGS, "Pack all the loose references in the repository."}, {"status", (PyCFunction)Repository_status, METH_NOARGS, "Reads the " "status of the repository and returns a dictionnary with file paths " "as keys and status flags as values.\nSee pygit2.GIT_STATUS_*."}, {"status_file", (PyCFunction)Repository_status_file, METH_O, "Returns the status of the given file path."}, {NULL} }; static PyGetSetDef Repository_getseters[] = { {"index", (getter)Repository_get_index, NULL, "index file. ", NULL}, {"path", (getter)Repository_get_path, NULL, "The normalized path to the git repository.", NULL}, {"workdir", (getter)Repository_get_workdir, NULL, "The normalized path to the working directory of the repository. " "If the repository is bare, None will be returned.", 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 = { PyVarObject_HEAD_INIT(NULL, 0) "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 | Py_TPFLAGS_HAVE_GC, /* tp_flags */ "Git repository", /* tp_doc */ (traverseproc)Repository_traverse, /* tp_traverse */ (inquiry)Repository_clear, /* 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_free(self->obj); Py_XDECREF(self->repo); PyObject_Del(self); } static PyObject * Object_get_oid(Object *self) { const git_oid *oid; oid = git_object_id(self->obj); assert(oid); return git_oid_to_python(oid->id); } static PyObject * Object_get_hex(Object *self) { const git_oid *oid; oid = git_object_id(self->obj); assert(oid); return git_oid_to_py_str(oid); } static PyObject * Object_get_type(Object *self) { return PyInt_FromLong(git_object_type(self->obj)); } static PyObject * Object_read_raw(Object *self) { const git_oid *oid; git_odb_object *obj; PyObject *aux; oid = git_object_id(self->obj); assert(oid); obj = Repository_read_raw(self->repo->repo, oid, GIT_OID_HEXSZ); if (obj == NULL) return NULL; aux = PyString_FromStringAndSize( git_odb_object_data(obj), git_odb_object_size(obj)); git_odb_object_free(obj); return aux; } static PyGetSetDef Object_getseters[] = { {"oid", (getter)Object_get_oid, NULL, "object id", NULL}, {"hex", (getter)Object_get_hex, NULL, "hex oid", NULL}, {"type", (getter)Object_get_type, NULL, "type number", 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 = { PyVarObject_HEAD_INIT(NULL, 0) "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_encoding(Commit *commit) { const char *encoding; encoding = git_commit_message_encoding(commit->commit); if (encoding == NULL) Py_RETURN_NONE; return to_encoding(encoding); } static PyObject * Commit_get_message(Commit *commit) { const char *message, *encoding; message = git_commit_message(commit->commit); encoding = git_commit_message_encoding(commit->commit); return to_unicode(message, encoding, "strict"); } static PyObject * Commit_get_commit_time(Commit *commit) { return PyLong_FromLong(git_commit_time(commit->commit)); } static PyObject * Commit_get_commit_time_offset(Commit *commit) { return PyLong_FromLong(git_commit_time_offset(commit->commit)); } static PyObject * Commit_get_committer(Commit *self) { const git_signature *signature; const char *encoding; signature = git_commit_committer(self->commit); encoding = git_commit_message_encoding(self->commit); return build_signature((Object*)self, signature, encoding); } static PyObject * Commit_get_author(Commit *self) { const git_signature *signature; const char *encoding; signature = git_commit_author(self->commit); encoding = git_commit_message_encoding(self->commit); return build_signature((Object*)self, signature, encoding); } 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); if (py_tree) { 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; const git_oid *parent_oid; 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++) { parent_oid = git_commit_parent_oid(commit->commit, i); if (parent_oid == NULL) { Py_DECREF(list); Error_set(GIT_ENOTFOUND); return NULL; } obj = lookup_object(commit->repo, parent_oid, GIT_OBJ_COMMIT); if (obj == NULL) { Py_DECREF(list); return NULL; } PyList_SET_ITEM(list, i, obj); } return list; } static PyGetSetDef Commit_getseters[] = { {"message_encoding", (getter)Commit_get_message_encoding, NULL, "message encoding", NULL}, {"message", (getter)Commit_get_message, NULL, "message", NULL}, {"commit_time", (getter)Commit_get_commit_time, NULL, "commit time", NULL}, {"commit_time_offset", (getter)Commit_get_commit_time_offset, NULL, "commit time offset", 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 = { PyVarObject_HEAD_INIT(NULL, 0) "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) { PyObject_Del(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 to_path(git_tree_entry_name(self->entry)); } static PyObject * TreeEntry_get_oid(TreeEntry *self) { const git_oid *oid; oid = git_tree_entry_id(self->entry); return git_oid_to_python(oid->id); } static PyObject * TreeEntry_get_hex(TreeEntry *self) { return git_oid_to_py_str(git_tree_entry_id(self->entry)); } static PyGetSetDef TreeEntry_getseters[] = { {"attributes", (getter)TreeEntry_get_attributes, NULL, "attributes", NULL}, {"name", (getter)TreeEntry_get_name, NULL, "name", NULL}, {"oid", (getter)TreeEntry_get_oid, NULL, "object id", NULL}, {"hex", (getter)TreeEntry_get_hex, NULL, "hex oid", NULL}, {NULL} }; static PyTypeObject TreeEntryType = { PyVarObject_HEAD_INIT(NULL, 0) "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 */ 0, /* 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 = py_path_to_c_str(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; py_entry = PyObject_New(TreeEntry, &TreeEntryType); if (py_entry) py_entry->entry = entry; return py_entry; } 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 PyObject * Tree_iter(Tree *self) { TreeIter *iter; iter = PyObject_New(TreeIter, &TreeIterType); if (iter) { Py_INCREF(self); iter->owner = self; iter->i = 0; } return (PyObject*)iter; } 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) { char *name; const git_tree_entry *entry; /* Case 1: integer */ if (PyInt_Check(value)) return Tree_getitem_by_index(self, value); /* Case 2: byte or text string */ name = py_path_to_c_str(value); if (name == NULL) return NULL; entry = git_tree_entry_byname(self->tree, name); if (!entry) { PyErr_SetObject(PyExc_KeyError, value); return NULL; } return wrap_tree_entry(entry, self); } 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 = { PyVarObject_HEAD_INIT(NULL, 0) "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 */ (getiterfunc)Tree_iter, /* 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 int TreeBuilder_init(TreeBuilder *self, PyObject *args, PyObject *kwds) { Tree *py_tree = NULL; git_tree *tree; int err; if (kwds) { PyErr_SetString(PyExc_TypeError, "TreeBuilder takes no keyword arguments"); return -1; } if (!PyArg_ParseTuple(args, "|O", &py_tree)) return -1; tree = py_tree == NULL ? NULL : py_tree->tree; err = git_treebuilder_create(&self->bld, tree); if (err < 0) { Error_set(err); return -1; } return 0; } static void TreeBuilder_dealloc(TreeBuilder* self) { git_treebuilder_free(self->bld); } static PyObject * TreeBuilder_insert(TreeBuilder *self, TreeEntry *py_tentry) { int err, attr; const git_oid *oid; const char *fname; const git_tree_entry *tentry; tentry = py_tentry->entry; fname = git_tree_entry_name(tentry); oid = git_tree_entry_id(tentry); attr = git_tree_entry_attributes(tentry); err = git_treebuilder_insert(NULL, self->bld, fname, oid, attr); if (err < 0) return Error_set(err); Py_RETURN_NONE; } static PyObject * TreeBuilder_write(TreeBuilder *self, Repository *py_repo) { int err; git_oid oid; git_repository *repo = py_repo->repo; err = git_treebuilder_write(&oid, repo, self->bld); if (err < 0) return Error_set(err); return git_oid_to_python(&oid); } static PyMethodDef TreeBuilder_methods[] = { {"insert", (PyCFunction)TreeBuilder_insert, METH_O, "Insert or replace an entry in the treebuilder"}, {"write", (PyCFunction)TreeBuilder_write, METH_O, "Write the tree to the given repository"}, {NULL, NULL, 0, NULL} }; static PyTypeObject TreeBuilderType = { PyVarObject_HEAD_INIT(NULL, 0) "pygit2.TreeBuilder", /* tp_name */ sizeof(TreeBuilder), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)TreeBuilder_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 */ "TreeBuilder objects", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TreeBuilder_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)TreeBuilder_init, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ }; static void TreeIter_dealloc(TreeIter *self) { Py_CLEAR(self->owner); PyObject_Del(self); } static TreeEntry * TreeIter_iternext(TreeIter *self) { const git_tree_entry *tree_entry; tree_entry = git_tree_entry_byindex(self->owner->tree, self->i); if (!tree_entry) return NULL; self->i += 1; return (TreeEntry*)wrap_tree_entry(tree_entry, self->owner); } static PyTypeObject TreeIterType = { PyVarObject_HEAD_INIT(NULL, 0) "pygit2.TreeIter", /* tp_name */ sizeof(TreeIter), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)TreeIter_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 */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)TreeIter_iternext, /* tp_iternext */ }; static PyGetSetDef Blob_getseters[] = { {"data", (getter)Object_read_raw, NULL, "raw data", NULL}, {NULL} }; static PyTypeObject BlobType = { PyVarObject_HEAD_INIT(NULL, 0) "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 PyObject * Tag_get_target(Tag *self) { const git_oid *target_oid; git_otype target_type; target_oid = git_tag_target_oid(self->tag); target_type = git_tag_type(self->tag); return lookup_object(self->repo, target_oid, target_type); } static PyObject * Tag_get_name(Tag *self) { const char *name; name = git_tag_name(self->tag); if (!name) Py_RETURN_NONE; return to_unicode(name, "utf-8", "strict"); } static PyObject * Tag_get_tagger(Tag *self) { const git_signature *signature = git_tag_tagger(self->tag); if (!signature) Py_RETURN_NONE; return build_signature((Object*)self, signature, "utf-8"); } static PyObject * Tag_get_message(Tag *self) { const char *message; message = git_tag_message(self->tag); if (!message) Py_RETURN_NONE; return to_unicode(message, "utf-8", "strict"); } 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 = { PyVarObject_HEAD_INIT(NULL, 0) "pygit2.Tag", /* tp_name */ sizeof(Tag), /* 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 */ "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 arguments"); return -1; } if (!PyArg_ParseTuple(args, "s", &path)) return -1; err = git_index_open(&self->index, path); if (err < 0) { Error_set_str(err, path); return -1; } return 0; } static void Index_dealloc(Index* self) { PyObject_GC_UnTrack(self); Py_XDECREF(self->repo); git_index_free(self->index); PyObject_GC_Del(self); } static int Index_traverse(Index *self, visitproc visit, void *arg) { Py_VISIT(self->repo); return 0; } 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; /* Case 1: integer */ 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; } return idx; } /* Case 2: byte or text string */ path = py_path_to_c_str(value); if (!path) return -1; idx = git_index_find(self->index, path); if (idx < 0) { Error_set_str(idx, path); return -1; } return idx; } static int Index_contains(Index *self, PyObject *value) { char *path; int idx; path = py_path_to_c_str(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 PyObject * Index_iter(Index *self) { IndexIter *iter; iter = PyObject_New(IndexIter, &IndexIterType); if (iter) { Py_INCREF(self); iter->owner = self; iter->i = 0; } return (PyObject*)iter; } static Py_ssize_t Index_len(Index *self) { return (Py_ssize_t)git_index_entrycount(self->index); } static PyObject * wrap_index_entry(git_index_entry *entry, Index *index) { IndexEntry *py_entry; py_entry = PyObject_New(IndexEntry, &IndexEntryType); if (py_entry) py_entry->entry = entry; return (PyObject*)py_entry; } static PyObject * Index_getitem(Index *self, PyObject *value) { int idx; git_index_entry *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; } return wrap_index_entry(index_entry, self); } 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_read_tree(Index *self, PyObject *value) { git_oid oid; git_tree *tree; size_t len; int err; len = py_str_to_git_oid(value, &oid); TODO_SUPPORT_SHORT_HEXS(len) if (len == 0) return NULL; err = git_tree_lookup_prefix(&tree, self->repo->repo, &oid, (unsigned int)len); if (err < 0) return Error_set(err); err = git_index_read_tree(self->index, tree); if (err < 0) return Error_set(err); Py_RETURN_NONE; } static PyObject * Index_write_tree(Index *self) { git_oid oid; int err; err = git_tree_create_fromindex(&oid, self->index); if (err < 0) return Error_set(err); return git_oid_to_python(oid.id); } 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."}, {"read_tree", (PyCFunction)Index_read_tree, METH_O, "Update the index file from the given tree object."}, {"write_tree", (PyCFunction)Index_write_tree, METH_NOARGS, "Create a tree object from the index file, return its oid."}, {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 = { PyVarObject_HEAD_INIT(NULL, 0) "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 | Py_TPFLAGS_HAVE_GC, /* tp_flags */ "Index file", /* tp_doc */ (traverseproc)Index_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)Index_iter, /* 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 IndexIter_dealloc(IndexIter *self) { Py_CLEAR(self->owner); PyObject_Del(self); } static PyObject * IndexIter_iternext(IndexIter *self) { git_index_entry *index_entry; index_entry = git_index_get(self->owner->index, self->i); if (!index_entry) return NULL; self->i += 1; return wrap_index_entry(index_entry, self->owner); } static PyTypeObject IndexIterType = { PyVarObject_HEAD_INIT(NULL, 0) "pygit2.IndexIter", /* tp_name */ sizeof(IndexIter), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)IndexIter_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 */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)IndexIter_iternext, /* tp_iternext */ }; static void IndexEntry_dealloc(IndexEntry *self) { PyObject_Del(self); } static PyObject * IndexEntry_get_mode(IndexEntry *self) { return PyInt_FromLong(self->entry->mode); } static PyObject * IndexEntry_get_path(IndexEntry *self) { return to_path(self->entry->path); } static PyObject * IndexEntry_get_oid(IndexEntry *self) { return git_oid_to_python(self->entry->oid.id); } static PyObject * IndexEntry_get_hex(IndexEntry *self) { return git_oid_to_py_str(&self->entry->oid); } static PyGetSetDef IndexEntry_getseters[] = { {"mode", (getter)IndexEntry_get_mode, NULL, "mode", NULL}, {"path", (getter)IndexEntry_get_path, NULL, "path", NULL}, {"oid", (getter)IndexEntry_get_oid, NULL, "object id", NULL}, {"hex", (getter)IndexEntry_get_hex, NULL, "hex oid", NULL}, {NULL}, }; static PyTypeObject IndexEntryType = { PyVarObject_HEAD_INIT(NULL, 0) "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); PyObject_Del(self); } static PyObject * Walker_hide(Walker *self, PyObject *py_hex) { int err; git_oid oid; size_t len; len = py_str_to_git_oid(py_hex, &oid); TODO_SUPPORT_SHORT_HEXS(len) if (len == 0) 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; size_t len; len = py_str_to_git_oid(py_hex, &oid); TODO_SUPPORT_SHORT_HEXS(len) if (len == 0) 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) { 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 = { PyVarObject_HEAD_INIT(NULL, 0) "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, /* 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 void Reference_dealloc(Reference *self) { git_reference_free(self->reference); PyObject_Del(self); } static PyObject * Reference_delete(Reference *self, PyObject *args) { int err; CHECK_REFERENCE(self); /* Delete the reference */ err = git_reference_delete(self->reference); if (err < 0) return Error_set(err); self->reference = NULL; /* Invalidate the pointer */ Py_RETURN_NONE; /* Return None */ } static PyObject * Reference_rename(Reference *self, PyObject *py_name) { char *c_name; int err; CHECK_REFERENCE(self); /* Get the C name */ c_name = py_path_to_c_str(py_name); if (c_name == NULL) return NULL; /* Rename */ err = git_reference_rename(self->reference, c_name, 0); if (err < 0) return Error_set(err); Py_RETURN_NONE; /* Return None */ } static PyObject * Reference_reload(Reference *self) { int err; CHECK_REFERENCE(self); err = git_reference_reload(self->reference); if (err < 0) { self->reference = NULL; return Error_set(err); } Py_RETURN_NONE; } static PyObject * Reference_resolve(Reference *self, PyObject *args) { git_reference *c_reference; int err; CHECK_REFERENCE(self); /* Direct: reload */ if (git_reference_type(self->reference) == GIT_REF_OID) { err = git_reference_reload(self->reference); if (err < 0) { self->reference = NULL; return Error_set(err); } Py_INCREF(self); return (PyObject *)self; } /* Symbolic: resolve */ err = git_reference_resolve(&c_reference, self->reference); if (err < 0) return Error_set(err); return wrap_reference(c_reference); } static PyObject * Reference_get_target(Reference *self) { const char * c_name; CHECK_REFERENCE(self); /* Get the target */ c_name = git_reference_target(self->reference); if (c_name == NULL) { PyErr_SetString(PyExc_ValueError, "no target available"); return NULL; } /* Make a PyString and return it */ return to_path(c_name); } static int Reference_set_target(Reference *self, PyObject *py_name) { char *c_name; int err; CHECK_REFERENCE_INT(self); /* Get the C name */ c_name = py_path_to_c_str(py_name); if (c_name == NULL) return -1; /* Set the new target */ err = git_reference_set_target(self->reference, c_name); if (err < 0) { Error_set(err); return -1; } return 0; } static PyObject * Reference_get_name(Reference *self) { CHECK_REFERENCE(self); return to_path(git_reference_name(self->reference)); } static PyObject * Reference_get_oid(Reference *self) { const git_oid *oid; CHECK_REFERENCE(self); /* Get the oid (only for "direct" references) */ oid = git_reference_oid(self->reference); if (oid == NULL) { PyErr_SetString(PyExc_ValueError, "oid is only available if the reference is direct " "(i.e. not symbolic)"); return NULL; } /* Convert and return it */ return git_oid_to_python(oid->id); } static int Reference_set_oid(Reference *self, PyObject *py_hex) { git_oid oid; int err; size_t len; CHECK_REFERENCE_INT(self); /* Get the oid */ len = py_str_to_git_oid(py_hex, &oid); TODO_SUPPORT_SHORT_HEXS(len) if (len == 0) return -1; /* Set the oid */ err = git_reference_set_oid(self->reference, &oid); if (err < 0) { Error_set(err); return -1; } return 0; } static PyObject * Reference_get_hex(Reference *self) { const git_oid *oid; CHECK_REFERENCE(self); /* Get the oid (only for "direct" references) */ oid = git_reference_oid(self->reference); if (oid == NULL) { PyErr_SetString(PyExc_ValueError, "oid is only available if the reference is direct " "(i.e. not symbolic)"); return NULL; } /* Convert and return it */ return git_oid_to_py_str(oid); } static PyObject * Reference_get_type(Reference *self) { git_rtype c_type; CHECK_REFERENCE(self); c_type = git_reference_type(self->reference); return PyInt_FromLong(c_type); } static PyMethodDef Reference_methods[] = { {"delete", (PyCFunction)Reference_delete, METH_NOARGS, "Delete this reference. It will no longer be valid!"}, {"rename", (PyCFunction)Reference_rename, METH_O, "Rename the reference."}, {"reload", (PyCFunction)Reference_reload, METH_NOARGS, "Reload the reference from the file-system."}, {"resolve", (PyCFunction)Reference_resolve, METH_NOARGS, "Resolve a symbolic reference and return a direct reference."}, {NULL} }; static PyGetSetDef Reference_getseters[] = { {"name", (getter)Reference_get_name, NULL, "The full name of a reference.", NULL}, {"oid", (getter)Reference_get_oid, (setter)Reference_set_oid, "object id", NULL}, {"hex", (getter)Reference_get_hex, NULL, "hex oid", NULL}, {"target", (getter)Reference_get_target, (setter)Reference_set_target, "target", NULL}, {"type", (getter)Reference_get_type, NULL, "type (GIT_REF_OID, GIT_REF_SYMBOLIC or GIT_REF_PACKED).", NULL}, {NULL} }; static PyTypeObject ReferenceType = { PyVarObject_HEAD_INIT(NULL, 0) "pygit2.Reference", /* tp_name */ sizeof(Reference), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)Reference_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 */ "Reference", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Reference_methods, /* tp_methods */ 0, /* tp_members */ Reference_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 Signature_init(Signature *self, PyObject *args, PyObject *kwds) { PyObject *py_name; char *name, *email, *encoding = NULL; long long time; int offset; int err; git_signature *signature; if (kwds) { PyErr_SetString(PyExc_TypeError, "Signature takes no keyword arguments"); return -1; } if (!PyArg_ParseTuple(args, "OsLi|s", &py_name, &email, &time, &offset, &encoding)) return -1; name = py_str_to_c_str(py_name, encoding); err = git_signature_new(&signature, name, email, time, offset); if (err < 0) { Error_set(err); return -1; } self->obj = NULL; self->signature = signature; if (encoding) { self->encoding = strdup(encoding); if (self->encoding == NULL) { PyErr_NoMemory(); return -1; } } return 0; } static void Signature_dealloc(Signature *self) { if (self->obj) Py_DECREF(self->obj); else { git_signature_free((git_signature*)self->signature); free((void*)self->encoding); } Py_TYPE(self)->tp_free((PyObject*)self); } static PyObject * Signature_get_encoding(Signature *self) { const char *encoding; encoding = self->encoding; if (encoding == NULL) encoding = "utf-8"; return to_encoding(encoding); } static PyObject * Signature_get_raw_name(Signature *self) { return to_bytes(self->signature->name); } static PyObject * Signature_get_raw_email(Signature *self) { return to_bytes(self->signature->email); } static PyObject * Signature_get_name(Signature *self) { return to_unicode(self->signature->name, self->encoding, "strict"); } static PyObject * Signature_get_email(Signature *self) { return to_unicode(self->signature->email, self->encoding, "strict"); } static PyObject * Signature_get_time(Signature *self) { return PyInt_FromLong(self->signature->when.time); } static PyObject * Signature_get_offset(Signature *self) { return PyInt_FromLong(self->signature->when.offset); } static PyGetSetDef Signature_getseters[] = { {"_encoding", (getter)Signature_get_encoding, NULL, "encoding", NULL}, {"_name", (getter)Signature_get_raw_name, NULL, "Name (bytes)", NULL}, {"_email", (getter)Signature_get_raw_email, NULL, "Email (bytes)", NULL}, {"name", (getter)Signature_get_name, NULL, "Name", NULL}, {"email", (getter)Signature_get_email, NULL, "Email", NULL}, {"time", (getter)Signature_get_time, NULL, "Time", NULL}, {"offset", (getter)Signature_get_offset, NULL, "Offset", NULL}, {NULL} }; static PyTypeObject SignatureType = { PyVarObject_HEAD_INIT(NULL, 0) "pygit2.Signature", /* tp_name */ sizeof(Signature), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)Signature_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 */ "Signature", /* 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 */ Signature_getseters, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)Signature_init, /* 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) return Error_set_str(err, path); py_repo = PyObject_GC_New(Repository, &RepositoryType); if (py_repo) { py_repo->repo = repo; py_repo->index = NULL; PyObject_GC_Track(py_repo); return (PyObject*)py_repo; } git_repository_free(repo); return NULL; }; static PyObject * discover_repository(PyObject *self, PyObject *args) { const char *path; int across_fs = 0; const char *ceiling_dirs = NULL; char repo_path[MAXPATHLEN]; int err; if (!PyArg_ParseTuple(args, "s|Is", &path, &across_fs, &ceiling_dirs)) return NULL; err = git_repository_discover(repo_path, sizeof(repo_path), path, across_fs, ceiling_dirs); if (err < 0) return Error_set_str(err, path); return to_path(repo_path); }; static PyMethodDef module_methods[] = { {"init_repository", init_repository, METH_VARARGS, "Creates a new Git repository in the given folder."}, {"discover_repository", discover_repository, METH_VARARGS, "Look for a git repository and return its path."}, {NULL} }; PyObject* moduleinit(PyObject* m) { if (m == NULL) return NULL; GitError = PyErr_NewException("pygit2.GitError", NULL, NULL); RepositoryType.tp_new = PyType_GenericNew; if (PyType_Ready(&RepositoryType) < 0) return NULL; /* Do not set 'tp_new' for Git objects. To create Git objects use the * Repository.create_XXX methods */ if (PyType_Ready(&ObjectType) < 0) return NULL; CommitType.tp_base = &ObjectType; if (PyType_Ready(&CommitType) < 0) return NULL; TreeType.tp_base = &ObjectType; if (PyType_Ready(&TreeType) < 0) return NULL; BlobType.tp_base = &ObjectType; if (PyType_Ready(&BlobType) < 0) return NULL; TagType.tp_base = &ObjectType; if (PyType_Ready(&TagType) < 0) return NULL; TreeEntryType.tp_new = PyType_GenericNew; if (PyType_Ready(&TreeEntryType) < 0) return NULL; IndexType.tp_new = PyType_GenericNew; if (PyType_Ready(&IndexType) < 0) return NULL; IndexEntryType.tp_new = PyType_GenericNew; if (PyType_Ready(&IndexEntryType) < 0) return NULL; TreeBuilderType.tp_new = PyType_GenericNew; if (PyType_Ready(&TreeBuilderType) < 0) return NULL; WalkerType.tp_new = PyType_GenericNew; if (PyType_Ready(&WalkerType) < 0) return NULL; ReferenceType.tp_new = PyType_GenericNew; if (PyType_Ready(&ReferenceType) < 0) return NULL; SignatureType.tp_new = PyType_GenericNew; if (PyType_Ready(&SignatureType) < 0) return NULL; 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(&TreeBuilderType); PyModule_AddObject(m, "TreeBuilder", (PyObject *)&TreeBuilderType); 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); Py_INCREF(&ReferenceType); PyModule_AddObject(m, "Reference", (PyObject *)&ReferenceType); Py_INCREF(&SignatureType); PyModule_AddObject(m, "Signature", (PyObject *)&SignatureType); 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); PyModule_AddIntConstant(m, "GIT_REF_OID", GIT_REF_OID); PyModule_AddIntConstant(m, "GIT_REF_SYMBOLIC", GIT_REF_SYMBOLIC); PyModule_AddIntConstant(m, "GIT_REF_PACKED", GIT_REF_PACKED); /* Git status flags */ PyModule_AddIntConstant(m, "GIT_STATUS_CURRENT", GIT_STATUS_CURRENT); PyModule_AddIntConstant(m, "GIT_STATUS_INDEX_NEW", GIT_STATUS_INDEX_NEW); PyModule_AddIntConstant(m, "GIT_STATUS_INDEX_MODIFIED", GIT_STATUS_INDEX_MODIFIED); PyModule_AddIntConstant(m, "GIT_STATUS_INDEX_DELETED" , GIT_STATUS_INDEX_DELETED); PyModule_AddIntConstant(m, "GIT_STATUS_WT_NEW", GIT_STATUS_WT_NEW); PyModule_AddIntConstant(m, "GIT_STATUS_WT_MODIFIED" , GIT_STATUS_WT_MODIFIED); PyModule_AddIntConstant(m, "GIT_STATUS_WT_DELETED", GIT_STATUS_WT_DELETED); /* Flags for ignored files */ PyModule_AddIntConstant(m, "GIT_STATUS_IGNORED", GIT_STATUS_IGNORED); return m; } #if PY_MAJOR_VERSION < 3 PyMODINIT_FUNC initpygit2(void) { PyObject* m; m = Py_InitModule3("pygit2", module_methods, "Python bindings for libgit2."); moduleinit(m); } #else static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "pygit2", /* m_name */ "Python bindings for libgit2.", /* m_doc */ -1, /* m_size */ module_methods, /* m_methods */ NULL, /* m_reload */ NULL, /* m_traverse */ NULL, /* m_clear */ NULL, /* m_free */ }; PyMODINIT_FUNC PyInit_pygit2(void) { PyObject* m; m = PyModule_Create(&moduledef); return moduleinit(m); } #endif