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:
15
include/pygit2/commit.h
Normal file
15
include/pygit2/commit.h
Normal 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
12
include/pygit2/error.h
Normal 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
19
include/pygit2/index.h
Normal 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
13
include/pygit2/object.h
Normal 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
15
include/pygit2/oid.h
Normal 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
|
18
include/pygit2/reference.h
Normal file
18
include/pygit2/reference.h
Normal 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
|
34
include/pygit2/repository.h
Normal file
34
include/pygit2/repository.h
Normal 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
|
17
include/pygit2/signature.h
Normal file
17
include/pygit2/signature.h
Normal 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
14
include/pygit2/tag.h
Normal 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
21
include/pygit2/tree.h
Normal 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
72
include/pygit2/types.h
Normal 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
69
include/pygit2/utils.h
Normal 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
16
include/pygit2/walker.h
Normal 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
|
8
setup.py
8
setup.py
@@ -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
261
src/pygit2.c
Normal 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
49
src/pygit2/blob.c
Normal 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
186
src/pygit2/commit.c
Normal 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
82
src/pygit2/error.c
Normal 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
492
src/pygit2/index.c
Normal 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
119
src/pygit2/object.c
Normal 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
95
src/pygit2/oid.c
Normal 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
300
src/pygit2/reference.c
Normal 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
806
src/pygit2/repository.c
Normal 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
179
src/pygit2/signature.c
Normal 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
102
src/pygit2/tag.c
Normal 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
462
src/pygit2/tree.c
Normal 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
36
src/pygit2/utils.c
Normal 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
157
src/pygit2/walker.c
Normal 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 */
|
||||
};
|
Reference in New Issue
Block a user