refactoring pygit2.c into several small files

The whole extension was organised in one big 3727 lines monster.
This refactoring is splitting these 3727 lines into several smaller files.
This commit is contained in:
Nico von Geyso
2012-05-25 13:59:59 +02:00
parent 6825bba8c0
commit 6b1a281edc
29 changed files with 3667 additions and 3347 deletions

15
include/pygit2/commit.h Normal file
View File

@@ -0,0 +1,15 @@
#ifndef INCLUDE_pygit2_commit_h
#define INCLUDE_pygit2_commit_h
#include <Python.h>
#include <git2.h>
PyObject* Commit_get_message_encoding(Commit *commit);
PyObject* Commit_get_message(Commit *commit);
PyObject* Commit_get_raw_message(Commit *commit);
PyObject* Commit_get_commit_time(Commit *commit);
PyObject* Commit_get_commit_time_offset(Commit *commit);
PyObject* Commit_get_committer(Commit *self);
PyObject* Commit_get_author(Commit *self);
#endif

12
include/pygit2/error.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef INCLUDE_pygit2_error_h
#define INCLUDE_pygit2_error_h
#include <Python.h>
#include <git2.h>
PyObject* Error_type(int type);
PyObject* Error_set(int err);
PyObject* Error_set_str(int err, const char *str);
PyObject* Error_set_oid(int err, const git_oid *oid, size_t len);
#endif

19
include/pygit2/index.h Normal file
View File

@@ -0,0 +1,19 @@
#ifndef INCLUDE_pygit2_index_h
#define INCLUDE_pygit2_index_h
#include <Python.h>
#include <git2.h>
PyObject* Index_add(Index *self, PyObject *args);
PyObject* Index_clear(Index *self);
PyObject* Index_find(Index *self, PyObject *py_path);
PyObject* Index_read(Index *self);
PyObject* Index_write(Index *self);
PyObject* Index_iter(Index *self);
PyObject* Index_getitem(Index *self, PyObject *value);
PyObject* Index_read_tree(Index *self, PyObject *value);
PyObject* Index_write_tree(Index *self);
Py_ssize_t Index_len(Index *self);
int Index_setitem(Index *self, PyObject *key, PyObject *value);
#endif

13
include/pygit2/object.h Normal file
View File

@@ -0,0 +1,13 @@
#ifndef INCLUDE_pygit2_object_h
#define INCLUDE_pygit2_object_h
#include <Python.h>
#include <git2.h>
#include <pygit2/types.h>
PyObject* Object_get_oid(Object *self);
PyObject* Object_get_hex(Object *self);
PyObject* Object_get_type(Object *self);
PyObject* Object_read_raw(Object *self);
#endif

15
include/pygit2/oid.h Normal file
View File

@@ -0,0 +1,15 @@
#ifndef INCLUDE_pygit2_oid_h
#define INCLUDE_pygit2_oid_h
#include <Python.h>
#include <git2.h>
int py_str_to_git_oid(PyObject *py_str, git_oid *oid);
int py_str_to_git_oid_expand(git_repository *repo, PyObject *py_str,
git_oid *oid);
PyObject* git_oid_to_py_str(const git_oid *oid);
#define git_oid_to_python(id) \
PyString_FromStringAndSize((const char*)id, GIT_OID_RAWSZ)
#endif

View File

@@ -0,0 +1,18 @@
#ifndef INCLUDE_pygit2_reference_h
#define INCLUDE_pygit2_reference_h
#include <Python.h>
#include <git2.h>
PyObject* Reference_delete(Reference *self, PyObject *args);
PyObject* Reference_rename(Reference *self, PyObject *py_name);
PyObject* Reference_reload(Reference *self);
PyObject* Reference_resolve(Reference *self, PyObject *args);
PyObject* Reference_get_target(Reference *self);
PyObject* Reference_get_name(Reference *self);
PyObject* Reference_get_oid(Reference *self);
PyObject* Reference_get_hex(Reference *self);
PyObject* Reference_get_type(Reference *self);
PyObject* wrap_reference(git_reference * c_reference);
#endif

View File

@@ -0,0 +1,34 @@
#ifndef INCLUDE_pygit2_repository_h
#define INCLUDE_pygit2_repository_h
#include <Python.h>
#include <git2.h>
#include <pygit2/types.h>
int Repository_init(Repository *self, PyObject *args, PyObject *kwds);
int Repository_traverse(Repository *self, visitproc visit, void *arg);
int Repository_clear(Repository *self);
int Repository_contains(Repository *self, PyObject *value);
git_odb_object* Repository_read_raw(git_repository *repo, const git_oid *oid, size_t len);
PyObject* Repository_getitem(Repository *self, PyObject *value);
PyObject* Repository_read(Repository *self, PyObject *py_hex);
PyObject* Repository_write(Repository *self, PyObject *args);
PyObject* Repository_get_index(Repository *self, void *closure);
PyObject* Repository_get_path(Repository *self, void *closure);
PyObject* Repository_get_workdir(Repository *self, void *closure);
PyObject* Repository_walk(Repository *self, PyObject *args);
PyObject* Repository_create_blob(Repository *self, PyObject *args);
PyObject* Repository_create_commit(Repository *self, PyObject *args);
PyObject* Repository_create_tag(Repository *self, PyObject *args);
PyObject* Repository_listall_references(Repository *self, PyObject *args);
PyObject* Repository_lookup_reference(Repository *self, PyObject *py_name);
PyObject* Repository_create_reference(Repository *self, PyObject *args);
PyObject* Repository_create_symbolic_reference(Repository *self, PyObject *args);
PyObject* Repository_packall_references(Repository *self, PyObject *args);
PyObject* Repository_status(Repository *self, PyObject *args);
PyObject* Repository_status_file(Repository *self, PyObject *value);
PyObject* Repository_TreeBuilder(Repository *self, PyObject *args);
#endif

View File

@@ -0,0 +1,17 @@
#ifndef INCLUDE_pygit2_signature_h
#define INCLUDE_pygit2_signature_h
#include <Python.h>
#include <git2.h>
#include <pygit2/types.h>
PyObject* Signature_get_encoding(Signature *self);
PyObject* Signature_get_raw_name(Signature *self);
PyObject* Signature_get_raw_email(Signature *self);
PyObject* Signature_get_name(Signature *self);
PyObject* Signature_get_email(Signature *self);
PyObject* Signature_get_time(Signature *self);
PyObject* Signature_get_offset(Signature *self);
PyObject* build_signature(Object *obj, const git_signature *signature, const char *encoding);
#endif

14
include/pygit2/tag.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef INCLUDE_pygit2_tag_h
#define INCLUDE_pygit2_tag_h
#include <Python.h>
#include <git2.h>
#include <pygit2/types.h>
PyObject* Tag_get_target(Tag *self);
PyObject* Tag_get_name(Tag *self);
PyObject* Tag_get_tagger(Tag *self);
PyObject* Tag_get_message(Tag *self);
PyObject* Tag_get_raw_message(Tag *self);
#endif

21
include/pygit2/tree.h Normal file
View File

@@ -0,0 +1,21 @@
#ifndef INCLUDE_pygit2_tree_h
#define INCLUDE_pygit2_tree_h
#include <Python.h>
#include <git2.h>
#include <pygit2/types.h>
PyObject* TreeEntry_get_attributes(TreeEntry *self);
PyObject* TreeEntry_get_name(TreeEntry *self);
PyObject* TreeEntry_get_oid(TreeEntry *self);
PyObject* TreeEntry_get_hex(TreeEntry *self);
PyObject* TreeEntry_to_object(TreeEntry *self);
TreeEntry* Tree_getitem_by_index(Tree *self, PyObject *py_index);
TreeEntry* Tree_getitem(Tree *self, PyObject *value);
PyObject* TreeBuilder_insert(TreeBuilder *self, PyObject *args);
PyObject* TreeBuilder_write(TreeBuilder *self);
PyObject* TreeBuilder_remove(TreeBuilder *self, PyObject *py_filename);
PyObject* TreeBuilder_clear(TreeBuilder *self);
#endif

72
include/pygit2/types.h Normal file
View File

@@ -0,0 +1,72 @@
#ifndef INCLUDE_pygit2_objects_h
#define INCLUDE_pygit2_objects_h
#include <Python.h>
#include <git2.h>
/* 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
PyObject *owner; /* Tree or TreeBuilder */
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;
PyObject* lookup_object_prefix(Repository *repo, const git_oid *oid, size_t len,
git_otype type);
PyObject* lookup_object(Repository *repo, const git_oid *oid, git_otype type);
#endif

69
include/pygit2/utils.h Normal file
View File

@@ -0,0 +1,69 @@
#ifndef INCLUDE_pygit2_utils_h
#define INCLUDE_pygit2_utils_h
#include <Python.h>
#include <git2.h>
#include <pygit2/types.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
#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;\
}
/* Utilities */
Py_LOCAL_INLINE(PyObject*)
to_unicode(const char *value, const char *encoding, const char *errors)
{
if (encoding == NULL) {
/* If the encoding is not explicit, it may not be UTF-8, so it
* is not safe to decode it strictly. This is rare in the
* wild, but does occur in old commits to git itself
* (e.g. c31820c2). */
encoding = "utf-8";
errors = "replace";
}
return PyUnicode_Decode(value, strlen(value), encoding, errors);
}
Py_LOCAL_INLINE(PyObject*)
to_bytes(const char * value)
{
return PyString_FromString(value);
}
char * py_str_to_c_str(PyObject *value, const char *encoding);
#define py_path_to_c_str(py_path) \
py_str_to_c_str(py_path, Py_FileSystemDefaultEncoding)
#endif

16
include/pygit2/walker.h Normal file
View File

@@ -0,0 +1,16 @@
#ifndef INCLUDE_pygit2_walker_h
#define INCLUDE_pygit2_walker_h
#include <Python.h>
#include <git2.h>
#include <pygit2/types.h>
void Walker_dealloc(Walker *self);
PyObject* Walker_hide(Walker *self, PyObject *py_hex);
PyObject* Walker_push(Walker *self, PyObject *py_hex);
PyObject* Walker_sort(Walker *self, PyObject *py_sort_mode);
PyObject* Walker_reset(Walker *self);
PyObject* Walker_iter(Walker *self);
PyObject* Walker_iternext(Walker *self);
#endif

3345
pygit2.c

File diff suppressed because it is too large Load Diff

View File

@@ -47,6 +47,10 @@ if libgit2_path is None:
libgit2_bin = os.path.join(libgit2_path, 'bin')
libgit2_include = os.path.join(libgit2_path, 'include')
libgit2_lib = os.path.join(libgit2_path, 'lib')
pygit2_exts = [os.path.join('src', 'pygit2.c')] + [
os.path.join('src', 'pygit2', entry)
for entry in os.listdir('src/pygit2')
if entry.endswith('.c')]
class TestCommand(Command):
"""Command for running unittests without install."""
@@ -139,8 +143,8 @@ setup(name='pygit2',
maintainer_email='jdavid.ibp@gmail.com',
long_description=long_description,
ext_modules=[
Extension('pygit2', ['pygit2.c'],
include_dirs=[libgit2_include],
Extension('pygit2', pygit2_exts,
include_dirs=[libgit2_include, 'include'],
library_dirs=[libgit2_lib],
libraries=['git2']),
],

261
src/pygit2.c Normal file
View File

@@ -0,0 +1,261 @@
/*
* 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 <pygit2/error.h>
#include <pygit2/types.h>
#include <pygit2/utils.h>
#include <pygit2/repository.h>
#include <git2.h>
extern PyObject *GitError;
PyTypeObject RepositoryType;
PyTypeObject ObjectType;
PyTypeObject CommitType;
PyTypeObject TreeType;
PyTypeObject TreeBuilderType;
PyTypeObject TreeEntryType;
PyTypeObject TreeIterType;
PyTypeObject BlobType;
PyTypeObject TagType;
PyTypeObject IndexType;
PyTypeObject IndexEntryType;
PyTypeObject IndexIterType;
PyTypeObject WalkerType;
PyTypeObject ReferenceType;
PyTypeObject SignatureType;
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;
};
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);
};
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(&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
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

49
src/pygit2/blob.c Normal file
View File

@@ -0,0 +1,49 @@
#include <Python.h>
#include <pygit2/object.h>
PyGetSetDef Blob_getseters[] = {
{"data", (getter)Object_read_raw, NULL, "raw data", NULL},
{NULL}
};
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 */
};

186
src/pygit2/commit.c Normal file
View File

@@ -0,0 +1,186 @@
#include <Python.h>
#include <pygit2/error.h>
#include <pygit2/utils.h>
#include <pygit2/signature.h>
#include <pygit2/commit.h>
#include <pygit2/oid.h>
#include <pygit2/repository.h>
extern PyTypeObject TreeType;
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);
}
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");
}
PyObject *
Commit_get_raw_message(Commit *commit)
{
return PyString_FromString(git_commit_message(commit->commit));
}
PyObject *
Commit_get_commit_time(Commit *commit)
{
return PyLong_FromLong(git_commit_time(commit->commit));
}
PyObject *
Commit_get_commit_time_offset(Commit *commit)
{
return PyLong_FromLong(git_commit_time_offset(commit->commit));
}
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);
}
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);
}
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;
}
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;
}
PyGetSetDef Commit_getseters[] = {
{"message_encoding", (getter)Commit_get_message_encoding, NULL,
"message encoding", NULL},
{"message", (getter)Commit_get_message, NULL, "message", NULL},
{"_message", (getter)Commit_get_raw_message, NULL, "message (bytes)", 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}
};
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 */
};

82
src/pygit2/error.c Normal file
View File

@@ -0,0 +1,82 @@
#include <pygit2/error.h>
PyObject *GitError;
PyObject * Error_type(int type)
{
// Expected
switch (type) {
/** Input does not exist in the scope searched. */
case GIT_ENOTFOUND:
return PyExc_KeyError;
/** A reference with this name already exists */
case GIT_EEXISTS:
return PyExc_ValueError;
/** The given short oid is ambiguous */
case GIT_EAMBIGUOUS:
return PyExc_ValueError;
/** The buffer is too short to satisfy the request */
case GIT_EBUFS:
return PyExc_ValueError;
/** Skip and passthrough the given ODB backend */
case GIT_PASSTHROUGH:
return GitError;
/** No entries left in ref walker */
case GIT_REVWALKOVER:
return PyExc_StopIteration;
}
// Critical
const git_error* error = giterr_last();
switch (error->klass) {
case GITERR_NOMEMORY:
return PyExc_MemoryError;
case GITERR_OS:
return PyExc_OSError;
case GITERR_INVALID:
return PyExc_ValueError;
default:
return GitError;
}
}
PyObject* Error_set(int err)
{
assert(err < 0);
if(err != GIT_ERROR) { //expected failure
PyErr_SetNone(Error_type(err));
} else { //critical failure
const git_error* error = giterr_last();
PyErr_SetString(Error_type(err), error->message);
}
return NULL;
}
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;
}
const git_error* error = giterr_last();
return PyErr_Format(Error_type(err), "%s: %s", str, error->message);
}
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);
}

492
src/pygit2/index.c Normal file
View File

@@ -0,0 +1,492 @@
#include <Python.h>
#include <pygit2/error.h>
#include <pygit2/types.h>
#include <pygit2/utils.h>
#include <pygit2/oid.h>
#include <pygit2/index.h>
extern PyTypeObject IndexType;
extern PyTypeObject IndexIterType;
extern PyTypeObject IndexEntryType;
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;
}
void
Index_dealloc(Index* self)
{
PyObject_GC_UnTrack(self);
Py_XDECREF(self->repo);
git_index_free(self->index);
PyObject_GC_Del(self);
}
int
Index_traverse(Index *self, visitproc visit, void *arg)
{
Py_VISIT(self->repo);
return 0;
}
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;
}
PyObject *
Index_clear(Index *self)
{
git_index_clear(self->index);
Py_RETURN_NONE;
}
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);
}
PyObject *
Index_read(Index *self)
{
int err;
err = git_index_read(self->index);
if (err < GIT_OK)
return Error_set(err);
Py_RETURN_NONE;
}
PyObject *
Index_write(Index *self)
{
int err;
err = git_index_write(self->index);
if (err < GIT_OK)
return Error_set(err);
Py_RETURN_NONE;
}
/* This is an internal function, used by Index_getitem and Index_setitem */
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);
free(path);
return -1;
}
return idx;
}
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);
free(path);
return -1;
}
return 1;
}
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;
}
Py_ssize_t
Index_len(Index *self)
{
return (Py_ssize_t)git_index_entrycount(self->index);
}
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;
}
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);
}
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;
}
PyObject *
Index_read_tree(Index *self, PyObject *value)
{
git_oid oid;
git_tree *tree;
int err, len;
len = py_str_to_git_oid(value, &oid);
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;
}
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);
}
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}
};
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 */
};
PyMappingMethods Index_as_mapping = {
(lenfunc)Index_len, /* mp_length */
(binaryfunc)Index_getitem, /* mp_subscript */
(objobjargproc)Index_setitem, /* mp_ass_subscript */
};
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 */
};
void
IndexIter_dealloc(IndexIter *self)
{
Py_CLEAR(self->owner);
PyObject_Del(self);
}
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);
}
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 */
};
void
IndexEntry_dealloc(IndexEntry *self)
{
PyObject_Del(self);
}
PyObject *
IndexEntry_get_mode(IndexEntry *self)
{
return PyInt_FromLong(self->entry->mode);
}
PyObject *
IndexEntry_get_path(IndexEntry *self)
{
return to_path(self->entry->path);
}
PyObject *
IndexEntry_get_oid(IndexEntry *self)
{
return git_oid_to_python(self->entry->oid.id);
}
PyObject *
IndexEntry_get_hex(IndexEntry *self)
{
return git_oid_to_py_str(&self->entry->oid);
}
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},
};
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 */
};

119
src/pygit2/object.c Normal file
View File

@@ -0,0 +1,119 @@
#include <Python.h>
#include <pygit2/error.h>
#include <pygit2/types.h>
#include <pygit2/utils.h>
#include <pygit2/oid.h>
#include <pygit2/repository.h>
#include <pygit2/object.h>
void
Object_dealloc(Object* self)
{
git_object_free(self->obj);
Py_XDECREF(self->repo);
PyObject_Del(self);
}
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);
}
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);
}
PyObject *
Object_get_type(Object *self)
{
return PyInt_FromLong(git_object_type(self->obj));
}
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;
}
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}
};
PyMethodDef Object_methods[] = {
{"read_raw", (PyCFunction)Object_read_raw, METH_NOARGS,
"Read the raw contents of the object from the repo."},
{NULL}
};
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 */
};

95
src/pygit2/oid.c Normal file
View File

@@ -0,0 +1,95 @@
#include <Python.h>
#include <git2.h>
#include <pygit2/utils.h>
#include <pygit2/error.h>
#include <pygit2/oid.h>
int
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 -1;
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 -1;
err = PyString_AsStringAndSize(py_hex, &hex_or_bin, &len);
if (err) {
Py_DECREF(py_hex);
return -1;
}
err = git_oid_fromstrn(oid, hex_or_bin, len);
Py_DECREF(py_hex);
if (err < 0) {
PyErr_SetObject(Error_type(err), py_str);
return -1;
}
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 -1;
}
int
py_str_to_git_oid_expand(git_repository *repo, PyObject *py_str, git_oid *oid)
{
int err;
int len;
git_odb *odb;
git_odb_object *obj;
len = py_str_to_git_oid(py_str, oid);
if (len == GIT_OID_HEXSZ || len < 0)
return len;
err = git_repository_odb(&odb, repo);
if (err < 0) {
Error_set(err);
return -1;
}
err = git_odb_read_prefix(&obj, odb, oid, len);
if (err < 0) {
git_odb_free(odb);
Error_set(err);
return err;
}
git_oid_cpy(oid, git_odb_object_id(obj));
git_odb_object_free(obj);
git_odb_free(odb);
return 0;
}
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");
}

300
src/pygit2/reference.c Normal file
View File

@@ -0,0 +1,300 @@
#include <Python.h>
#include <pygit2/error.h>
#include <pygit2/types.h>
#include <pygit2/utils.h>
#include <pygit2/oid.h>
#include <pygit2/reference.h>
extern PyObject *GitError;
void
Reference_dealloc(Reference *self)
{
git_reference_free(self->reference);
PyObject_Del(self);
}
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 */
}
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);
free(c_name);
if (err < 0)
return Error_set(err);
Py_RETURN_NONE; /* Return None */
}
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;
}
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);
}
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);
}
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);
free(c_name);
if (err < 0) {
Error_set(err);
return -1;
}
return 0;
}
PyObject *
Reference_get_name(Reference *self)
{
CHECK_REFERENCE(self);
return to_path(git_reference_name(self->reference));
}
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);
}
int
Reference_set_oid(Reference *self, PyObject *py_hex)
{
git_oid oid;
int err;
CHECK_REFERENCE_INT(self);
/* Get the oid */
err = py_str_to_git_oid_expand(git_reference_owner(self->reference), py_hex, &oid);
if (err < 0) {
Error_set(err);
return -1;
}
/* Set the oid */
err = git_reference_set_oid(self->reference, &oid);
if (err < 0) {
Error_set(err);
return -1;
}
return 0;
}
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);
}
PyObject *
Reference_get_type(Reference *self)
{
git_ref_t c_type;
CHECK_REFERENCE(self);
c_type = git_reference_type(self->reference);
return PyInt_FromLong(c_type);
}
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}
};
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}
};
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 */
};
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;
}

806
src/pygit2/repository.c Normal file
View File

@@ -0,0 +1,806 @@
#include <Python.h>
#include <pygit2/error.h>
#include <pygit2/types.h>
#include <pygit2/reference.h>
#include <pygit2/utils.h>
#include <pygit2/oid.h>
#include <pygit2/repository.h>
extern PyTypeObject IndexType;
extern PyTypeObject WalkerType;
extern PyTypeObject SignatureType;
extern PyTypeObject TreeType;
extern PyTypeObject CommitType;
extern PyTypeObject BlobType;
extern PyTypeObject TagType;
extern PyTypeObject TreeBuilderType;
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;
}
}
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;
}
PyObject *
lookup_object(Repository *repo, const git_oid *oid, git_otype type)
{
return lookup_object_prefix(repo, oid, GIT_OID_HEXSZ, type);
}
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;
}
void
Repository_dealloc(Repository *self)
{
PyObject_GC_UnTrack(self);
Py_XDECREF(self->index);
git_repository_free(self->repo);
PyObject_GC_Del(self);
}
int
Repository_traverse(Repository *self, visitproc visit, void *arg)
{
Py_VISIT(self->index);
return 0;
}
int
Repository_clear(Repository *self)
{
Py_CLEAR(self->index);
return 0;
}
int
Repository_contains(Repository *self, PyObject *value)
{
git_oid oid;
git_odb *odb;
int err, len, exists;
len = py_str_to_git_oid(value, &oid);
if (len < 0)
return -1;
err = git_repository_odb(&odb, self->repo);
if (err < 0) {
Error_set(err);
return -1;
}
if (len < GIT_OID_HEXSZ) {
git_odb_object *obj = NULL;
err = git_odb_read_prefix(&obj, odb, &oid, len);
if (err < 0 && err != GIT_ENOTFOUND) {
Error_set(err);
exists = -1;
} else {
exists = (err == 0);
if (obj)
git_odb_object_free(obj);
}
} else {
exists = git_odb_exists(odb, &oid);
}
git_odb_free(odb);
return exists;
}
PyObject *
Repository_getitem(Repository *self, PyObject *value)
{
git_oid oid;
int len;
len = py_str_to_git_oid(value, &oid);
if (len < 0)
return NULL;
return lookup_object_prefix(self, &oid, len, GIT_OBJ_ANY);
}
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;
}
PyObject *
Repository_read(Repository *self, PyObject *py_hex)
{
git_oid oid;
git_odb_object *obj;
int 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;
}
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);
}
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;
}
PyObject *
Repository_get_path(Repository *self, void *closure)
{
return to_path(git_repository_path(self->repo));
}
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);
}
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;
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) {
err = py_str_to_git_oid_expand(self->repo, value, &oid);
if (err < 0) {
git_revwalk_free(walk);
return Error_set(err);
}
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;
}
PyObject *
Repository_create_blob(Repository *self, PyObject *args)
{
git_oid oid;
const char* raw;
Py_ssize_t size;
int err;
if (!PyArg_ParseTuple(args, "s#", &raw, &size))
return NULL;
err = git_blob_create_frombuffer(&oid, self->repo, (const void*)raw, size);
if (err < 0)
return Error_set(err);
return git_oid_to_python(oid.id);
}
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 = NULL;
char *update_ref = NULL;
char *encoding = NULL;
git_oid oid;
git_tree *tree = NULL;
int parent_count;
git_commit **parents = NULL;
int err = 0, i = 0, 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);
if (message == NULL)
goto out;
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:
free(message);
git_tree_free(tree);
while (i > 0) {
i--;
git_commit_free(parents[i]);
}
free(parents);
return py_result;
}
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, 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);
}
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_list(&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;
}
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) {
PyObject *err_obj = Error_set_str(err, c_name);
free(c_name);
return err_obj;
}
/* 3- Make an instance of Reference and return it */
return wrap_reference(c_reference);
}
PyObject *
Repository_create_reference(Repository *self, PyObject *args)
{
PyObject *py_oid;
git_reference *c_reference;
char *c_name;
git_oid oid;
int err;
/* 1- Get the C variables */
if (!PyArg_ParseTuple(args, "sO", &c_name, &py_oid))
return NULL;
err = py_str_to_git_oid_expand(self->repo, py_oid, &oid);
if (err < 0)
return Error_set(err);
/* 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);
}
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);
}
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;
}
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_OK;
}
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;
}
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) {
PyObject *err_obj = Error_set_str(err, path);
free(path);
return err_obj;
}
return PyInt_FromLong(status);
}
PyObject *
Repository_TreeBuilder(Repository *self, PyObject *args)
{
TreeBuilder *builder;
git_treebuilder *bld;
PyObject *py_src = NULL;
git_oid oid;
git_tree *tree = NULL;
git_tree *must_free = NULL;
int err;
if (!PyArg_ParseTuple(args, "|O", &py_src))
return NULL;
if (py_src) {
if (PyObject_TypeCheck(py_src, &TreeType)) {
Tree *py_tree = (Tree *)py_src;
if (py_tree->repo->repo != self->repo) {
//return Error_set(GIT_EINVALIDARGS);
return Error_set(GIT_ERROR);
}
tree = py_tree->tree;
} else {
err = py_str_to_git_oid_expand(self->repo, py_src, &oid);
if (err < 0)
return NULL;
err = git_tree_lookup(&tree, self->repo, &oid);
if (err < 0)
return Error_set(err);
must_free = tree;
}
}
err = git_treebuilder_create(&bld, tree);
if (must_free != NULL) {
git_tree_free(must_free);
}
if (err < 0)
return Error_set(err);
builder = PyObject_New(TreeBuilder, &TreeBuilderType);
if (builder) {
builder->repo = self;
builder->bld = bld;
Py_INCREF(self);
}
return (PyObject*)builder;
}
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_blob", (PyCFunction)Repository_create_blob,
METH_VARARGS,
"Create a new blob from memory"},
{"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 dictionary 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."},
{"TreeBuilder", (PyCFunction)Repository_TreeBuilder, METH_VARARGS,
"Create a TreeBuilder object for this repository."},
{NULL}
};
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}
};
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 */
};
PyMappingMethods Repository_as_mapping = {
0, /* mp_length */
(binaryfunc)Repository_getitem, /* mp_subscript */
0, /* mp_ass_subscript */
};
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 */
};

179
src/pygit2/signature.c Normal file
View File

@@ -0,0 +1,179 @@
#include <Python.h>
#include <pygit2/error.h>
#include <pygit2/types.h>
#include <pygit2/utils.h>
#include <pygit2/oid.h>
#include <pygit2/signature.h>
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);
if (name == NULL)
return -1;
err = git_signature_new(&signature, name, email, time, offset);
free(name);
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;
}
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);
}
PyObject *
Signature_get_encoding(Signature *self)
{
const char *encoding;
encoding = self->encoding;
if (encoding == NULL)
encoding = "utf-8";
return to_encoding(encoding);
}
PyObject *
Signature_get_raw_name(Signature *self)
{
return to_bytes(self->signature->name);
}
PyObject *
Signature_get_raw_email(Signature *self)
{
return to_bytes(self->signature->email);
}
PyObject *
Signature_get_name(Signature *self)
{
return to_unicode(self->signature->name, self->encoding, "strict");
}
PyObject *
Signature_get_email(Signature *self)
{
return to_unicode(self->signature->email, self->encoding, "strict");
}
PyObject *
Signature_get_time(Signature *self)
{
return PyInt_FromLong(self->signature->when.time);
}
PyObject *
Signature_get_offset(Signature *self)
{
return PyInt_FromLong(self->signature->when.offset);
}
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}
};
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 */
};
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;
}

102
src/pygit2/tag.c Normal file
View File

@@ -0,0 +1,102 @@
#include <Python.h>
#include <pygit2/error.h>
#include <pygit2/types.h>
#include <pygit2/utils.h>
#include <pygit2/signature.h>
#include <pygit2/oid.h>
#include <pygit2/tag.h>
PyObject *
Tag_get_target(Tag *self)
{
const git_oid *oid;
oid = git_tag_target_oid(self->tag);
return git_oid_to_python(oid->id);
}
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");
}
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");
}
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");
}
PyObject *
Tag_get_raw_message(Tag *self)
{
return PyString_FromString(git_tag_message(self->tag));
}
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},
{"_message", (getter)Tag_get_raw_message, NULL, "tag message (bytes)", NULL},
{NULL}
};
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 */
};

462
src/pygit2/tree.c Normal file
View File

@@ -0,0 +1,462 @@
#include <Python.h>
#include <pygit2/error.h>
#include <pygit2/utils.h>
#include <pygit2/repository.h>
#include <pygit2/oid.h>
#include <pygit2/tree.h>
extern PyTypeObject TreeType;
extern PyTypeObject TreeIterType;
void
TreeEntry_dealloc(TreeEntry *self)
{
Py_XDECREF(self->owner);
PyObject_Del(self);
}
PyObject *
TreeEntry_get_attributes(TreeEntry *self)
{
return PyInt_FromLong(git_tree_entry_attributes(self->entry));
}
PyObject *
TreeEntry_get_name(TreeEntry *self)
{
return to_path(git_tree_entry_name(self->entry));
}
PyObject *
TreeEntry_get_oid(TreeEntry *self)
{
const git_oid *oid;
oid = git_tree_entry_id(self->entry);
return git_oid_to_python(oid->id);
}
PyObject *
TreeEntry_get_hex(TreeEntry *self)
{
return git_oid_to_py_str(git_tree_entry_id(self->entry));
}
PyObject *
TreeEntry_to_object(TreeEntry *self)
{
const git_oid *entry_oid;
Repository *repo;
repo = ((Object*)(self->owner))->repo;
entry_oid = git_tree_entry_id(self->entry);
return lookup_object(repo, entry_oid, GIT_OBJ_ANY);
}
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}
};
PyMethodDef TreeEntry_methods[] = {
{"to_object", (PyCFunction)TreeEntry_to_object, METH_NOARGS,
"Look up the corresponding object in the repo."},
{NULL, NULL, 0, NULL}
};
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 */
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 */
};
Py_ssize_t
Tree_len(Tree *self)
{
assert(self->tree);
return (Py_ssize_t)git_tree_entrycount(self->tree);
}
int
Tree_contains(Tree *self, PyObject *py_name)
{
int result = 0;
char *name = py_path_to_c_str(py_name);
if (name == NULL)
return -1;
result = git_tree_entry_byname(self->tree, name) ? 1 : 0;
free(name);
return result;
}
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;
py_entry->owner = (PyObject*)tree;
Py_INCREF(tree);
}
return py_entry;
}
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;
}
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;
}
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);
}
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);
free(name);
if (!entry) {
PyErr_SetObject(PyExc_KeyError, value);
return NULL;
}
return wrap_tree_entry(entry, self);
}
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 */
};
PyMappingMethods Tree_as_mapping = {
(lenfunc)Tree_len, /* mp_length */
(binaryfunc)Tree_getitem, /* mp_subscript */
0, /* mp_ass_subscript */
};
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 */
};
void
TreeBuilder_dealloc(TreeBuilder* self)
{
Py_XDECREF(self->repo);
git_treebuilder_free(self->bld);
PyObject_Del(self);
}
PyObject *
TreeBuilder_insert(TreeBuilder *self, PyObject *args)
{
PyObject *py_oid;
int len, err, attr;
git_oid oid;
const char *fname;
if (!PyArg_ParseTuple(args, "sOi", &fname, &py_oid, &attr)) {
return NULL;
}
len = py_str_to_git_oid(py_oid, &oid);
if (len < 0) {
return NULL;
}
err = git_treebuilder_insert(NULL, self->bld, fname, &oid, attr);
if (err < 0) {
Error_set(err);
return NULL;
}
Py_RETURN_NONE;
}
PyObject *
TreeBuilder_write(TreeBuilder *self)
{
int err;
git_oid oid;
err = git_treebuilder_write(&oid, self->repo->repo, self->bld);
if (err < 0)
return Error_set(err);
return git_oid_to_python(&oid);
}
PyObject *
TreeBuilder_remove(TreeBuilder *self, PyObject *py_filename)
{
char *filename = py_path_to_c_str(py_filename);
int err = 0;
if (filename == NULL)
return NULL;
err = git_treebuilder_remove(self->bld, filename);
free(filename);
if (err < 0)
return Error_set(err);
Py_RETURN_NONE;
}
PyObject *
TreeBuilder_clear(TreeBuilder *self)
{
git_treebuilder_clear(self->bld);
Py_RETURN_NONE;
}
PyMethodDef TreeBuilder_methods[] = {
{"insert", (PyCFunction)TreeBuilder_insert, METH_VARARGS,
"Insert or replace an entry in the treebuilder"},
{"write", (PyCFunction)TreeBuilder_write, METH_NOARGS,
"Write the tree to the given repository"},
{"remove", (PyCFunction)TreeBuilder_remove, METH_O,
"Remove an entry from the builder"},
{"clear", (PyCFunction)TreeBuilder_clear, METH_NOARGS,
"Clear all the entries in the builder"},
{NULL, NULL, 0, NULL}
};
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 */
0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};
void
TreeIter_dealloc(TreeIter *self)
{
Py_CLEAR(self->owner);
PyObject_Del(self);
}
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);
}
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 */
};

36
src/pygit2/utils.c Normal file
View File

@@ -0,0 +1,36 @@
#include <pygit2/error.h>
#include <pygit2/utils.h>
extern PyTypeObject ReferenceType;
// py_str_to_c_str() returns a newly allocated C string holding
// the string contained in the value argument.
char * py_str_to_c_str(PyObject *value, const char *encoding)
{
/* Case 1: byte string */
if (PyString_Check(value))
return strdup(PyString_AsString(value));
/* Case 2: text string */
if (PyUnicode_Check(value)) {
char *c_str = NULL;
if (encoding == NULL)
value = PyUnicode_AsUTF8String(value);
else
value = PyUnicode_AsEncodedString(value, encoding, "strict");
if (value == NULL)
return NULL;
c_str = strdup(PyString_AsString(value));
Py_DECREF(value);
return c_str;
}
/* Type error */
PyErr_Format(PyExc_TypeError, "unexpected %.200s",
Py_TYPE(value)->tp_name);
return NULL;
}

157
src/pygit2/walker.c Normal file
View File

@@ -0,0 +1,157 @@
#include <Python.h>
#include <pygit2/error.h>
#include <pygit2/utils.h>
#include <pygit2/oid.h>
#include <pygit2/tree.h>
#include <pygit2/walker.h>
extern PyTypeObject CommitType;
void
Walker_dealloc(Walker *self)
{
git_revwalk_free(self->walk);
Py_DECREF(self->repo);
PyObject_Del(self);
}
PyObject *
Walker_hide(Walker *self, PyObject *py_hex)
{
int err;
git_oid oid;
err = py_str_to_git_oid_expand(self->repo->repo, py_hex, &oid);
if (err < 0)
return Error_set(err);
err = git_revwalk_hide(self->walk, &oid);
if (err < 0)
return Error_set(err);
Py_RETURN_NONE;
}
PyObject *
Walker_push(Walker *self, PyObject *py_hex)
{
int err;
git_oid oid;
err = py_str_to_git_oid_expand(self->repo->repo, py_hex, &oid);
if (err < 0)
return Error_set(err);
err = git_revwalk_push(self->walk, &oid);
if (err < 0)
return Error_set(err);
Py_RETURN_NONE;
}
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;
}
PyObject *
Walker_reset(Walker *self)
{
git_revwalk_reset(self->walk);
Py_RETURN_NONE;
}
PyObject *
Walker_iter(Walker *self)
{
Py_INCREF(self);
return (PyObject*)self;
}
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;
}
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}
};
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 */
};