Synchronized with upstream
This commit is contained in:
12
.travis.sh
Executable file
12
.travis.sh
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
cd ~
|
||||||
|
|
||||||
|
git clone -b master https://github.com/libgit2/libgit2.git
|
||||||
|
cd libgit2/
|
||||||
|
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake .. -DCMAKE_INSTALL_PREFIX=../_install
|
||||||
|
cmake --build . --target install
|
||||||
|
|
||||||
|
ls -la ..
|
||||||
14
.travis.yml
Normal file
14
.travis.yml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
language: python
|
||||||
|
|
||||||
|
python:
|
||||||
|
- "2.7"
|
||||||
|
- "3.2"
|
||||||
|
|
||||||
|
env: LIBGIT2=~/libgit2/_install/ LD_LIBRARY_PATH=~/libgit2/_install/lib
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- sudo apt-get install cmake
|
||||||
|
- "./.travis.sh"
|
||||||
|
|
||||||
|
script:
|
||||||
|
- python setup.py test
|
||||||
@@ -6,6 +6,11 @@
|
|||||||
#include <git2.h>
|
#include <git2.h>
|
||||||
#include <pygit2/types.h>
|
#include <pygit2/types.h>
|
||||||
|
|
||||||
|
#define DIFF_CHECK_TYPES(_x, _y, _type_x, _type_y) \
|
||||||
|
PyObject_TypeCheck(_x, _type_x) && \
|
||||||
|
PyObject_TypeCheck(_y, _type_y)
|
||||||
|
|
||||||
|
|
||||||
PyObject* Diff_changes(Diff *self);
|
PyObject* Diff_changes(Diff *self);
|
||||||
PyObject* Diff_patch(Diff *self);
|
PyObject* Diff_patch(Diff *self);
|
||||||
|
|
||||||
|
|||||||
@@ -45,8 +45,7 @@ typedef struct {
|
|||||||
int new_start;
|
int new_start;
|
||||||
int new_lines;
|
int new_lines;
|
||||||
char* new_file;
|
char* new_file;
|
||||||
PyObject *old_data;
|
PyObject *data;
|
||||||
PyObject *new_data;
|
|
||||||
} Hunk;
|
} Hunk;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -71,6 +70,23 @@ typedef struct {
|
|||||||
git_reference *reference;
|
git_reference *reference;
|
||||||
} Reference;
|
} Reference;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
PyObject *oid_old;
|
||||||
|
PyObject *oid_new;
|
||||||
|
PyObject *committer;
|
||||||
|
char *msg;
|
||||||
|
} RefLogEntry;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
Reference *reference;
|
||||||
|
git_reflog *reflog;
|
||||||
|
int i;
|
||||||
|
int size;
|
||||||
|
} RefLogIter;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
Object *obj;
|
Object *obj;
|
||||||
|
|||||||
15
src/pygit2.c
15
src/pygit2.c
@@ -53,6 +53,8 @@ PyTypeObject IndexEntryType;
|
|||||||
PyTypeObject IndexIterType;
|
PyTypeObject IndexIterType;
|
||||||
PyTypeObject WalkerType;
|
PyTypeObject WalkerType;
|
||||||
PyTypeObject ReferenceType;
|
PyTypeObject ReferenceType;
|
||||||
|
PyTypeObject RefLogIterType;
|
||||||
|
PyTypeObject RefLogEntryType;
|
||||||
PyTypeObject SignatureType;
|
PyTypeObject SignatureType;
|
||||||
|
|
||||||
|
|
||||||
@@ -131,12 +133,6 @@ moduleinit(PyObject* m)
|
|||||||
CommitType.tp_base = &ObjectType;
|
CommitType.tp_base = &ObjectType;
|
||||||
if (PyType_Ready(&CommitType) < 0)
|
if (PyType_Ready(&CommitType) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
DiffType.tp_base = &ObjectType;
|
|
||||||
if (PyType_Ready(&DiffType) < 0)
|
|
||||||
return NULL;
|
|
||||||
HunkType.tp_base = &ObjectType;
|
|
||||||
if (PyType_Ready(&HunkType) < 0)
|
|
||||||
return NULL;
|
|
||||||
TreeType.tp_base = &ObjectType;
|
TreeType.tp_base = &ObjectType;
|
||||||
if (PyType_Ready(&TreeType) < 0)
|
if (PyType_Ready(&TreeType) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -147,6 +143,11 @@ moduleinit(PyObject* m)
|
|||||||
if (PyType_Ready(&TagType) < 0)
|
if (PyType_Ready(&TagType) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (PyType_Ready(&DiffType) < 0)
|
||||||
|
return NULL;
|
||||||
|
if (PyType_Ready(&HunkType) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
TreeEntryType.tp_new = PyType_GenericNew;
|
TreeEntryType.tp_new = PyType_GenericNew;
|
||||||
if (PyType_Ready(&TreeEntryType) < 0)
|
if (PyType_Ready(&TreeEntryType) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -165,6 +166,8 @@ moduleinit(PyObject* m)
|
|||||||
ReferenceType.tp_new = PyType_GenericNew;
|
ReferenceType.tp_new = PyType_GenericNew;
|
||||||
if (PyType_Ready(&ReferenceType) < 0)
|
if (PyType_Ready(&ReferenceType) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
if (PyType_Ready(&RefLogEntryType) < 0)
|
||||||
|
return NULL;
|
||||||
SignatureType.tp_new = PyType_GenericNew;
|
SignatureType.tp_new = PyType_GenericNew;
|
||||||
if (PyType_Ready(&SignatureType) < 0)
|
if (PyType_Ready(&SignatureType) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@@ -6,6 +6,10 @@
|
|||||||
#include <pygit2/utils.h>
|
#include <pygit2/utils.h>
|
||||||
#include <pygit2/diff.h>
|
#include <pygit2/diff.h>
|
||||||
|
|
||||||
|
extern PyObject *GitError;
|
||||||
|
|
||||||
|
extern PyTypeObject TreeType;
|
||||||
|
extern PyTypeObject IndexType;
|
||||||
extern PyTypeObject DiffType;
|
extern PyTypeObject DiffType;
|
||||||
extern PyTypeObject HunkType;
|
extern PyTypeObject HunkType;
|
||||||
|
|
||||||
@@ -13,11 +17,11 @@ static int diff_data_cb(
|
|||||||
void *cb_data,
|
void *cb_data,
|
||||||
git_diff_delta *delta,
|
git_diff_delta *delta,
|
||||||
git_diff_range *range,
|
git_diff_range *range,
|
||||||
char usage,
|
char line_origin,
|
||||||
const char *line,
|
const char *content,
|
||||||
size_t line_len)
|
size_t content_len)
|
||||||
{
|
{
|
||||||
PyObject *hunks, *tmp;
|
PyObject *hunks, *data, *tmp;
|
||||||
Hunk *hunk;
|
Hunk *hunk;
|
||||||
Py_ssize_t size;
|
Py_ssize_t size;
|
||||||
|
|
||||||
@@ -30,13 +34,14 @@ static int diff_data_cb(
|
|||||||
if (hunk == NULL)
|
if (hunk == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
tmp = PyBytes_FromStringAndSize(line, line_len);
|
tmp = PyBytes_FromStringAndSize(content, content_len);
|
||||||
|
|
||||||
if(usage != GIT_DIFF_LINE_DELETION)
|
data = Py_BuildValue("(O,i)",
|
||||||
PyBytes_Concat(&hunk->new_data, tmp);
|
tmp,
|
||||||
|
line_origin
|
||||||
|
);
|
||||||
|
|
||||||
if(usage != GIT_DIFF_LINE_ADDITION)
|
PyList_Append(hunk->data, data);
|
||||||
PyBytes_Concat(&hunk->old_data, tmp);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -58,6 +63,8 @@ static int diff_hunk_cb(
|
|||||||
}
|
}
|
||||||
|
|
||||||
hunk = (Hunk*)PyType_GenericNew(&HunkType, NULL, NULL);
|
hunk = (Hunk*)PyType_GenericNew(&HunkType, NULL, NULL);
|
||||||
|
if (hunk == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
hunk->old_start = range->old_start;
|
hunk->old_start = range->old_start;
|
||||||
hunk->old_lines = range->old_lines;
|
hunk->old_lines = range->old_lines;
|
||||||
@@ -67,23 +74,27 @@ static int diff_hunk_cb(
|
|||||||
int len;
|
int len;
|
||||||
char* old_path, *new_path;
|
char* old_path, *new_path;
|
||||||
|
|
||||||
|
if (delta->old_file.path != NULL) {
|
||||||
len = strlen(delta->old_file.path) + 1;
|
len = strlen(delta->old_file.path) + 1;
|
||||||
old_path = malloc(sizeof(char) * len);
|
old_path = malloc(sizeof(char) * len);
|
||||||
memcpy(old_path, delta->old_file.path, len);
|
memcpy(old_path, delta->old_file.path, len);
|
||||||
hunk->old_file = old_path;
|
hunk->old_file = old_path;
|
||||||
|
} else {
|
||||||
|
hunk->old_file = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delta->new_file.path != NULL) {
|
||||||
len = strlen(delta->new_file.path) + 1;
|
len = strlen(delta->new_file.path) + 1;
|
||||||
new_path = malloc(sizeof(char) * len);
|
new_path = malloc(sizeof(char) * len);
|
||||||
memcpy(new_path, delta->new_file.path, len);
|
memcpy(new_path, delta->new_file.path, len);
|
||||||
hunk->new_file = new_path;
|
hunk->new_file = new_path;
|
||||||
|
} else {
|
||||||
|
hunk->new_file = "";
|
||||||
|
}
|
||||||
|
|
||||||
#if PY_MAJOR_VERSION >= 3
|
if (hunk->data == NULL) {
|
||||||
hunk->old_data = Py_BuildValue("y", "");
|
hunk->data = PyList_New(0);
|
||||||
hunk->new_data = Py_BuildValue("y", "");
|
}
|
||||||
#else
|
|
||||||
hunk->old_data = Py_BuildValue("s", "");
|
|
||||||
hunk->new_data = Py_BuildValue("s", "");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PyList_Append(hunks, (PyObject *)hunk);
|
PyList_Append(hunks, (PyObject *)hunk);
|
||||||
|
|
||||||
@@ -94,7 +105,9 @@ static int diff_file_cb(void *cb_data, git_diff_delta *delta, float progress)
|
|||||||
{
|
{
|
||||||
PyObject *files, *file;
|
PyObject *files, *file;
|
||||||
|
|
||||||
|
if(delta->old_file.path != NULL && delta->new_file.path != NULL) {
|
||||||
files = PyDict_GetItemString(cb_data, "files");
|
files = PyDict_GetItemString(cb_data, "files");
|
||||||
|
|
||||||
if(files == NULL) {
|
if(files == NULL) {
|
||||||
files = PyList_New(0);
|
files = PyList_New(0);
|
||||||
PyDict_SetItemString(cb_data, "files", files);
|
PyDict_SetItemString(cb_data, "files", files);
|
||||||
@@ -107,6 +120,7 @@ static int diff_file_cb(void *cb_data, git_diff_delta *delta, float progress)
|
|||||||
);
|
);
|
||||||
|
|
||||||
PyList_Append(files, file);
|
PyList_Append(files, file);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -161,15 +175,9 @@ Hunk_init(Hunk *self, PyObject *args, PyObject *kwds)
|
|||||||
self->new_start = 0;
|
self->new_start = 0;
|
||||||
self->new_lines = 0;
|
self->new_lines = 0;
|
||||||
|
|
||||||
self->old_data = PyString_FromString("");
|
self->data = PyList_New(0);
|
||||||
if (self->old_data == NULL) {
|
if (self->data == NULL) {
|
||||||
Py_DECREF(self);
|
Py_XDECREF(self);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
self->new_data = PyString_FromString("");
|
|
||||||
if (self->new_data == NULL) {
|
|
||||||
Py_DECREF(self);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,8 +187,7 @@ Hunk_init(Hunk *self, PyObject *args, PyObject *kwds)
|
|||||||
static void
|
static void
|
||||||
Hunk_dealloc(Hunk *self)
|
Hunk_dealloc(Hunk *self)
|
||||||
{
|
{
|
||||||
Py_XDECREF(self->old_data);
|
Py_XDECREF(self->data);
|
||||||
Py_XDECREF(self->new_data);
|
|
||||||
PyObject_Del(self);
|
PyObject_Del(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,17 +195,16 @@ PyMemberDef Hunk_members[] = {
|
|||||||
{"old_start", T_INT, offsetof(Hunk, old_start), 0, "old start"},
|
{"old_start", T_INT, offsetof(Hunk, old_start), 0, "old start"},
|
||||||
{"old_lines", T_INT, offsetof(Hunk, old_lines), 0, "old lines"},
|
{"old_lines", T_INT, offsetof(Hunk, old_lines), 0, "old lines"},
|
||||||
{"old_file", T_STRING, offsetof(Hunk, old_file), 0, "old file"},
|
{"old_file", T_STRING, offsetof(Hunk, old_file), 0, "old file"},
|
||||||
{"old_data", T_OBJECT, offsetof(Hunk, old_data), 0, "old data"},
|
|
||||||
{"new_start", T_INT, offsetof(Hunk, new_start), 0, "new start"},
|
{"new_start", T_INT, offsetof(Hunk, new_start), 0, "new start"},
|
||||||
{"new_lines", T_INT, offsetof(Hunk, new_lines), 0, "new lines"},
|
{"new_lines", T_INT, offsetof(Hunk, new_lines), 0, "new lines"},
|
||||||
{"new_file", T_STRING, offsetof(Hunk, new_file), 0, "old file"},
|
{"new_file", T_STRING, offsetof(Hunk, new_file), 0, "old file"},
|
||||||
{"new_data", T_OBJECT, offsetof(Hunk, new_data), 0, "new data"},
|
{"data", T_OBJECT, offsetof(Hunk, data), 0, "data"},
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
PyTypeObject HunkType = {
|
PyTypeObject HunkType = {
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
"pygit2.Hunk", /* tp_name */
|
"_pygit2.Hunk", /* tp_name */
|
||||||
sizeof(Hunk), /* tp_basicsize */
|
sizeof(Hunk), /* tp_basicsize */
|
||||||
0, /* tp_itemsize */
|
0, /* tp_itemsize */
|
||||||
(destructor)Hunk_dealloc, /* tp_dealloc */
|
(destructor)Hunk_dealloc, /* tp_dealloc */
|
||||||
@@ -277,7 +283,7 @@ static PyMethodDef Diff_methods[] = {
|
|||||||
|
|
||||||
PyTypeObject DiffType = {
|
PyTypeObject DiffType = {
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
"pygit2.Diff", /* tp_name */
|
"_pygit2.Diff", /* tp_name */
|
||||||
sizeof(Diff), /* tp_basicsize */
|
sizeof(Diff), /* tp_basicsize */
|
||||||
0, /* tp_itemsize */
|
0, /* tp_itemsize */
|
||||||
(destructor)Diff_dealloc, /* tp_dealloc */
|
(destructor)Diff_dealloc, /* tp_dealloc */
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ PyObject * Error_type(int type)
|
|||||||
|
|
||||||
// Critical
|
// Critical
|
||||||
const git_error* error = giterr_last();
|
const git_error* error = giterr_last();
|
||||||
|
if(error != NULL) {
|
||||||
switch (error->klass) {
|
switch (error->klass) {
|
||||||
case GITERR_NOMEMORY:
|
case GITERR_NOMEMORY:
|
||||||
return PyExc_MemoryError;
|
return PyExc_MemoryError;
|
||||||
@@ -40,10 +41,10 @@ PyObject * Error_type(int type)
|
|||||||
return PyExc_OSError;
|
return PyExc_OSError;
|
||||||
case GITERR_INVALID:
|
case GITERR_INVALID:
|
||||||
return PyExc_ValueError;
|
return PyExc_ValueError;
|
||||||
default:
|
|
||||||
return GitError;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return GitError;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PyObject* Error_set(int err)
|
PyObject* Error_set(int err)
|
||||||
@@ -54,7 +55,10 @@ PyObject* Error_set(int err)
|
|||||||
PyErr_SetNone(Error_type(err));
|
PyErr_SetNone(Error_type(err));
|
||||||
} else { //critical failure
|
} else { //critical failure
|
||||||
const git_error* error = giterr_last();
|
const git_error* error = giterr_last();
|
||||||
PyErr_SetString(Error_type(err), error->message);
|
char* message = (error == NULL) ?
|
||||||
|
"(No error information given)" : error->message;
|
||||||
|
|
||||||
|
PyErr_SetString(Error_type(err), message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
#include <pygit2/index.h>
|
#include <pygit2/index.h>
|
||||||
|
|
||||||
extern PyTypeObject IndexType;
|
extern PyTypeObject IndexType;
|
||||||
|
extern PyTypeObject TreeType;
|
||||||
|
extern PyTypeObject DiffType;
|
||||||
extern PyTypeObject IndexIterType;
|
extern PyTypeObject IndexIterType;
|
||||||
extern PyTypeObject IndexEntryType;
|
extern PyTypeObject IndexEntryType;
|
||||||
|
|
||||||
@@ -74,6 +76,48 @@ Index_clear(Index *self)
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
Index_diff_tree(Index *self, PyObject *args)
|
||||||
|
{
|
||||||
|
git_diff_options opts = {0};
|
||||||
|
git_diff_list *diff;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
Diff *py_diff;
|
||||||
|
PyObject *py_obj = NULL;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "|O", &py_obj))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (py_obj == NULL) {
|
||||||
|
err = git_diff_workdir_to_index(
|
||||||
|
self->repo->repo,
|
||||||
|
&opts,
|
||||||
|
&diff);
|
||||||
|
} else if (PyObject_TypeCheck(py_obj, &TreeType)) {
|
||||||
|
err = git_diff_index_to_tree(
|
||||||
|
self->repo->repo,
|
||||||
|
&opts,
|
||||||
|
((Tree *)py_obj)->tree,
|
||||||
|
&diff);
|
||||||
|
} else {
|
||||||
|
PyErr_SetObject(PyExc_TypeError, py_obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (err < 0)
|
||||||
|
return Error_set(err);
|
||||||
|
|
||||||
|
py_diff = PyObject_New(Diff, &DiffType);
|
||||||
|
if (py_diff) {
|
||||||
|
Py_INCREF(py_diff);
|
||||||
|
Py_INCREF(self->repo);
|
||||||
|
py_diff->repo = self->repo;
|
||||||
|
py_diff->diff = diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (PyObject*)py_diff;
|
||||||
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
Index_find(Index *self, PyObject *py_path)
|
Index_find(Index *self, PyObject *py_path)
|
||||||
{
|
{
|
||||||
@@ -285,6 +329,8 @@ PyMethodDef Index_methods[] = {
|
|||||||
"Add or update an index entry from a file in disk."},
|
"Add or update an index entry from a file in disk."},
|
||||||
{"clear", (PyCFunction)Index_clear, METH_NOARGS,
|
{"clear", (PyCFunction)Index_clear, METH_NOARGS,
|
||||||
"Clear the contents (all the entries) of an index object."},
|
"Clear the contents (all the entries) of an index object."},
|
||||||
|
{"diff", (PyCFunction)Index_diff_tree, METH_VARARGS,
|
||||||
|
"Diff index to tree."},
|
||||||
{"_find", (PyCFunction)Index_find, METH_O,
|
{"_find", (PyCFunction)Index_find, METH_O,
|
||||||
"Find the first index of any entries which point to given path in the"
|
"Find the first index of any entries which point to given path in the"
|
||||||
" Git index."},
|
" Git index."},
|
||||||
|
|||||||
@@ -1,12 +1,100 @@
|
|||||||
#define PY_SSIZE_T_CLEAN
|
#define PY_SSIZE_T_CLEAN
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <structmember.h>
|
||||||
#include <pygit2/error.h>
|
#include <pygit2/error.h>
|
||||||
#include <pygit2/types.h>
|
#include <pygit2/types.h>
|
||||||
#include <pygit2/utils.h>
|
#include <pygit2/utils.h>
|
||||||
#include <pygit2/oid.h>
|
#include <pygit2/oid.h>
|
||||||
|
#include <pygit2/signature.h>
|
||||||
#include <pygit2/reference.h>
|
#include <pygit2/reference.h>
|
||||||
|
|
||||||
|
|
||||||
extern PyObject *GitError;
|
extern PyObject *GitError;
|
||||||
|
extern PyTypeObject RefLogEntryType;
|
||||||
|
|
||||||
|
|
||||||
|
void RefLogIter_dealloc(RefLogIter *self)
|
||||||
|
{
|
||||||
|
Py_XDECREF(self->reference);
|
||||||
|
git_reflog_free(self->reflog);
|
||||||
|
PyObject_GC_Del(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* RefLogIter_iternext(PyObject *self)
|
||||||
|
{
|
||||||
|
RefLogIter *p = (RefLogIter *) self;
|
||||||
|
|
||||||
|
if (p->i < p->size) {
|
||||||
|
char oid_old[40], oid_new[40];
|
||||||
|
RefLogEntry *py_entry;
|
||||||
|
git_signature *signature;
|
||||||
|
|
||||||
|
const git_reflog_entry *entry = git_reflog_entry_byindex(p->reflog, p->i);
|
||||||
|
|
||||||
|
py_entry = (RefLogEntry*) PyType_GenericNew(
|
||||||
|
&RefLogEntryType, NULL, NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
git_oid_fmt(oid_old, git_reflog_entry_oidold(entry));
|
||||||
|
git_oid_fmt(oid_new, git_reflog_entry_oidnew(entry));
|
||||||
|
|
||||||
|
py_entry->oid_new = PyUnicode_FromStringAndSize(oid_new, 40);
|
||||||
|
py_entry->oid_old = PyUnicode_FromStringAndSize(oid_old, 40);
|
||||||
|
|
||||||
|
py_entry->msg = strdup(git_reflog_entry_msg(entry));
|
||||||
|
|
||||||
|
signature = git_signature_dup(
|
||||||
|
git_reflog_entry_committer(entry)
|
||||||
|
);
|
||||||
|
|
||||||
|
if(signature != NULL)
|
||||||
|
py_entry->committer = build_signature(
|
||||||
|
(Object*)py_entry, signature, "utf-8"
|
||||||
|
);
|
||||||
|
|
||||||
|
++(p->i);
|
||||||
|
|
||||||
|
return (PyObject*) py_entry;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
PyErr_SetNone(PyExc_StopIteration);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyTypeObject RefLogIterType = {
|
||||||
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
|
"_libgit2.RefLogIter", /*tp_name*/
|
||||||
|
sizeof(RefLogIter), /*tp_basicsize*/
|
||||||
|
0, /*tp_itemsize*/
|
||||||
|
(destructor)RefLogIter_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 */
|
||||||
|
/* tp_flags: Py_TPFLAGS_HAVE_ITER tells python to
|
||||||
|
use tp_iter and tp_iternext fields. */
|
||||||
|
"Internal reflog iterator object.", /* tp_doc */
|
||||||
|
0, /* tp_traverse */
|
||||||
|
0, /* tp_clear */
|
||||||
|
0, /* tp_richcompare */
|
||||||
|
0, /* tp_weaklistoffset */
|
||||||
|
PyObject_SelfIter, /* tp_iter: __iter__() method */
|
||||||
|
(iternextfunc) RefLogIter_iternext /* tp_iternext: next() method */
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
Reference_dealloc(Reference *self)
|
Reference_dealloc(Reference *self)
|
||||||
@@ -221,6 +309,97 @@ Reference_get_type(Reference *self)
|
|||||||
return PyInt_FromLong(c_type);
|
return PyInt_FromLong(c_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
Reference_log(Reference *self)
|
||||||
|
{
|
||||||
|
RefLogIter *iter;
|
||||||
|
|
||||||
|
CHECK_REFERENCE(self);
|
||||||
|
|
||||||
|
iter = PyObject_New(RefLogIter, &RefLogIterType);
|
||||||
|
if (iter) {
|
||||||
|
iter->reference = self;
|
||||||
|
git_reflog_read(&iter->reflog, self->reference);
|
||||||
|
iter->size = git_reflog_entrycount(iter->reflog);
|
||||||
|
iter->i = 0;
|
||||||
|
|
||||||
|
Py_INCREF(self);
|
||||||
|
Py_INCREF(iter);
|
||||||
|
}
|
||||||
|
return (PyObject*)iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
RefLogEntry_init(RefLogEntry *self, PyObject *args, PyObject *kwds)
|
||||||
|
{
|
||||||
|
self->oid_old = Py_None;
|
||||||
|
self->oid_new = Py_None;
|
||||||
|
self->msg = "";
|
||||||
|
self->committer = Py_None;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
RefLogEntry_dealloc(RefLogEntry *self)
|
||||||
|
{
|
||||||
|
Py_XDECREF(self->oid_old);
|
||||||
|
Py_XDECREF(self->oid_new);
|
||||||
|
Py_XDECREF(self->committer);
|
||||||
|
free(self->msg);
|
||||||
|
PyObject_Del(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyMemberDef RefLogEntry_members[] = {
|
||||||
|
{"oid_new", T_OBJECT, offsetof(RefLogEntry, oid_new), 0, "new oid"},
|
||||||
|
{"oid_old", T_OBJECT, offsetof(RefLogEntry, oid_old), 0, "old oid"},
|
||||||
|
{"message", T_STRING, offsetof(RefLogEntry, msg), 0, "message"},
|
||||||
|
{"committer", T_OBJECT, offsetof(RefLogEntry, committer), 0, "committer"},
|
||||||
|
{NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
PyTypeObject RefLogEntryType = {
|
||||||
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
|
"_pygit2.RefLogEntry", /* tp_name */
|
||||||
|
sizeof(RefLogEntry), /* tp_basicsize */
|
||||||
|
0, /* tp_itemsize */
|
||||||
|
(destructor)RefLogEntry_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 */
|
||||||
|
"ReferenceLog object", /* tp_doc */
|
||||||
|
0, /* tp_traverse */
|
||||||
|
0, /* tp_clear */
|
||||||
|
0, /* tp_richcompare */
|
||||||
|
0, /* tp_weaklistoffset */
|
||||||
|
0, /* tp_iter */
|
||||||
|
0, /* tp_iternext */
|
||||||
|
0, /* tp_methods */
|
||||||
|
RefLogEntry_members, /* tp_members */
|
||||||
|
0, /* tp_getset */
|
||||||
|
0, /* tp_base */
|
||||||
|
0, /* tp_dict */
|
||||||
|
0, /* tp_descr_get */
|
||||||
|
0, /* tp_descr_set */
|
||||||
|
0, /* tp_dictoffset */
|
||||||
|
(initproc)RefLogEntry_init, /* tp_init */
|
||||||
|
0, /* tp_alloc */
|
||||||
|
0, /* tp_new */
|
||||||
|
};
|
||||||
|
|
||||||
PyMethodDef Reference_methods[] = {
|
PyMethodDef Reference_methods[] = {
|
||||||
{"delete", (PyCFunction)Reference_delete, METH_NOARGS,
|
{"delete", (PyCFunction)Reference_delete, METH_NOARGS,
|
||||||
"Delete this reference. It will no longer be valid!"},
|
"Delete this reference. It will no longer be valid!"},
|
||||||
@@ -230,6 +409,8 @@ PyMethodDef Reference_methods[] = {
|
|||||||
"Reload the reference from the file-system."},
|
"Reload the reference from the file-system."},
|
||||||
{"resolve", (PyCFunction)Reference_resolve, METH_NOARGS,
|
{"resolve", (PyCFunction)Reference_resolve, METH_NOARGS,
|
||||||
"Resolve a symbolic reference and return a direct reference."},
|
"Resolve a symbolic reference and return a direct reference."},
|
||||||
|
{"log", (PyCFunction)Reference_log, METH_NOARGS,
|
||||||
|
"Retrieves the current reference log."},
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ extern PyTypeObject CommitType;
|
|||||||
extern PyTypeObject BlobType;
|
extern PyTypeObject BlobType;
|
||||||
extern PyTypeObject TagType;
|
extern PyTypeObject TagType;
|
||||||
extern PyTypeObject TreeBuilderType;
|
extern PyTypeObject TreeBuilderType;
|
||||||
|
extern PyTypeObject DiffType;
|
||||||
|
|
||||||
git_otype
|
git_otype
|
||||||
int_to_loose_object_type(int type_id)
|
int_to_loose_object_type(int type_id)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
extern PyTypeObject TreeType;
|
extern PyTypeObject TreeType;
|
||||||
extern PyTypeObject DiffType;
|
extern PyTypeObject DiffType;
|
||||||
extern PyTypeObject TreeIterType;
|
extern PyTypeObject TreeIterType;
|
||||||
|
extern PyTypeObject IndexType;
|
||||||
|
|
||||||
void
|
void
|
||||||
TreeEntry_dealloc(TreeEntry *self)
|
TreeEntry_dealloc(TreeEntry *self)
|
||||||
@@ -236,19 +237,34 @@ Tree_diff_tree(Tree *self, PyObject *args)
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
Diff *py_diff;
|
Diff *py_diff;
|
||||||
Tree *py_tree;
|
PyObject *py_obj = NULL;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O!", &TreeType, &py_tree))
|
if (!PyArg_ParseTuple(args, "|O", &py_obj))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (py_tree->repo->repo != self->repo->repo)
|
|
||||||
return Error_set(GIT_ERROR);
|
|
||||||
|
|
||||||
|
if (py_obj == NULL) {
|
||||||
|
err = git_diff_workdir_to_tree(
|
||||||
|
self->repo->repo,
|
||||||
|
&opts,
|
||||||
|
self->tree,
|
||||||
|
&diff);
|
||||||
|
} else if (PyObject_TypeCheck(py_obj, &TreeType)) {
|
||||||
err = git_diff_tree_to_tree(
|
err = git_diff_tree_to_tree(
|
||||||
self->repo->repo,
|
self->repo->repo,
|
||||||
&opts,
|
&opts,
|
||||||
self->tree,
|
self->tree,
|
||||||
py_tree->tree,
|
((Tree *)py_obj)->tree,
|
||||||
&diff);
|
&diff);
|
||||||
|
} else if (PyObject_TypeCheck(py_obj, &IndexType)) {
|
||||||
|
err = git_diff_index_to_tree(
|
||||||
|
((Index *)py_obj)->repo->repo,
|
||||||
|
&opts,
|
||||||
|
self->tree,
|
||||||
|
&diff);
|
||||||
|
} else {
|
||||||
|
PyErr_SetObject(PyExc_TypeError, py_obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return Error_set(err);
|
return Error_set(err);
|
||||||
|
|
||||||
@@ -281,8 +297,14 @@ PyMappingMethods Tree_as_mapping = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
PyMethodDef Tree_methods[] = {
|
PyMethodDef Tree_methods[] = {
|
||||||
{"diff", (PyCFunction)Tree_diff_tree, METH_VARARGS,
|
{
|
||||||
"Diff two trees."},
|
"diff", (PyCFunction)Tree_diff_tree, METH_VARARGS,
|
||||||
|
"Get changes between current tree instance with another tree, an "
|
||||||
|
"index or the working dir.\n\n"
|
||||||
|
"@param obj : if not given compare diff against working dir. "
|
||||||
|
"Possible valid arguments are instances of Tree or Index.\n"
|
||||||
|
"@returns Diff instance"
|
||||||
|
},
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ __author__ = 'Nico.Geyso@FU-Berlin.de (Nico von Geyso)'
|
|||||||
COMMIT_SHA1_1 = '5fe808e8953c12735680c257f56600cb0de44b10'
|
COMMIT_SHA1_1 = '5fe808e8953c12735680c257f56600cb0de44b10'
|
||||||
COMMIT_SHA1_2 = 'c2792cfa289ae6321ecf2cd5806c2194b0fd070c'
|
COMMIT_SHA1_2 = 'c2792cfa289ae6321ecf2cd5806c2194b0fd070c'
|
||||||
COMMIT_SHA1_3 = '2cdae28389c059815e951d0bb9eed6533f61a46b'
|
COMMIT_SHA1_3 = '2cdae28389c059815e951d0bb9eed6533f61a46b'
|
||||||
|
|
||||||
PATCH = b"""diff --git a/a b/a
|
PATCH = b"""diff --git a/a b/a
|
||||||
index 7f129fd..af431f2 100644
|
index 7f129fd..af431f2 100644
|
||||||
--- a/a
|
--- a/a
|
||||||
@@ -56,6 +57,45 @@ index 297efb8..0000000
|
|||||||
-c/d contents
|
-c/d contents
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
DIFF_INDEX_EXPECTED = [
|
||||||
|
'staged_changes',
|
||||||
|
'staged_changes_file_deleted',
|
||||||
|
'staged_changes_file_modified',
|
||||||
|
'staged_delete',
|
||||||
|
'staged_delete_file_modified',
|
||||||
|
'staged_new',
|
||||||
|
'staged_new_file_deleted',
|
||||||
|
'staged_new_file_modified'
|
||||||
|
]
|
||||||
|
|
||||||
|
DIFF_WORKDIR_EXPECTED = [
|
||||||
|
'file_deleted',
|
||||||
|
'modified_file',
|
||||||
|
'staged_changes',
|
||||||
|
'staged_changes_file_deleted',
|
||||||
|
'staged_changes_file_modified',
|
||||||
|
'staged_delete',
|
||||||
|
'staged_delete_file_modified',
|
||||||
|
'subdir/deleted_file',
|
||||||
|
'subdir/modified_file'
|
||||||
|
]
|
||||||
|
|
||||||
|
class DiffDirtyTest(utils.DirtyRepoTestCase):
|
||||||
|
def test_diff_empty_index(self):
|
||||||
|
repo = self.repo
|
||||||
|
head = repo[repo.lookup_reference('HEAD').resolve().oid]
|
||||||
|
diff = head.tree.diff(repo.index)
|
||||||
|
|
||||||
|
files = [x[1] for x in diff.changes['files']]
|
||||||
|
self.assertEqual(DIFF_INDEX_EXPECTED, files)
|
||||||
|
|
||||||
|
def test_workdir_to_tree(self):
|
||||||
|
repo = self.repo
|
||||||
|
head = repo[repo.lookup_reference('HEAD').resolve().oid]
|
||||||
|
diff = head.tree.diff()
|
||||||
|
|
||||||
|
files = [x[1] for x in diff.changes['files']]
|
||||||
|
self.assertEqual(DIFF_WORKDIR_EXPECTED, files)
|
||||||
|
|
||||||
class DiffTest(utils.BareRepoTestCase):
|
class DiffTest(utils.BareRepoTestCase):
|
||||||
|
|
||||||
@@ -64,6 +104,14 @@ class DiffTest(utils.BareRepoTestCase):
|
|||||||
commit_b = self.repo[COMMIT_SHA1_2]
|
commit_b = self.repo[COMMIT_SHA1_2]
|
||||||
self.assertRaises(TypeError, commit_a.tree.diff, commit_b)
|
self.assertRaises(TypeError, commit_a.tree.diff, commit_b)
|
||||||
|
|
||||||
|
def test_diff_empty_index(self):
|
||||||
|
repo = self.repo
|
||||||
|
head = repo[repo.lookup_reference('HEAD').resolve().oid]
|
||||||
|
diff = head.tree.diff(repo.index)
|
||||||
|
|
||||||
|
files = [x[0].split('/')[0] for x in diff.changes['files']]
|
||||||
|
self.assertEqual([x.name for x in head.tree], files)
|
||||||
|
|
||||||
def test_diff_tree(self):
|
def test_diff_tree(self):
|
||||||
commit_a = self.repo[COMMIT_SHA1_1]
|
commit_a = self.repo[COMMIT_SHA1_1]
|
||||||
commit_b = self.repo[COMMIT_SHA1_2]
|
commit_b = self.repo[COMMIT_SHA1_2]
|
||||||
@@ -83,8 +131,8 @@ class DiffTest(utils.BareRepoTestCase):
|
|||||||
self.assertEqual(hunk.old_file, 'a')
|
self.assertEqual(hunk.old_file, 'a')
|
||||||
self.assertEqual(hunk.new_file, 'a')
|
self.assertEqual(hunk.new_file, 'a')
|
||||||
|
|
||||||
self.assertEqual(hunk.old_data, b'a contents 2\n')
|
#self.assertEqual(hunk.data[0][0], b'a contents 2\n')
|
||||||
self.assertEqual(hunk.new_data, b'a contents\n')
|
#self.assertEqual(hunk.data[1][0], b'a contents\n')
|
||||||
|
|
||||||
def test_diff_merge(self):
|
def test_diff_merge(self):
|
||||||
commit_a = self.repo[COMMIT_SHA1_1]
|
commit_a = self.repo[COMMIT_SHA1_1]
|
||||||
@@ -113,8 +161,8 @@ class DiffTest(utils.BareRepoTestCase):
|
|||||||
self.assertEqual(hunk.old_file, 'b')
|
self.assertEqual(hunk.old_file, 'b')
|
||||||
self.assertEqual(hunk.new_file, 'b')
|
self.assertEqual(hunk.new_file, 'b')
|
||||||
|
|
||||||
self.assertEqual(hunk.old_data, b'b contents\n')
|
#self.assertEqual(hunk.data[0][0], b'b contents\n')
|
||||||
self.assertEqual(hunk.new_data, b'b contents 2\n')
|
#self.assertEqual(hunk.data[1][0], b'b contents 2\n')
|
||||||
|
|
||||||
def test_diff_patch(self):
|
def test_diff_patch(self):
|
||||||
commit_a = self.repo[COMMIT_SHA1_1]
|
commit_a = self.repo[COMMIT_SHA1_1]
|
||||||
|
|||||||
@@ -46,6 +46,23 @@ log = [
|
|||||||
'6aaa262e655dd54252e5813c8e5acd7780ed097d',
|
'6aaa262e655dd54252e5813c8e5acd7780ed097d',
|
||||||
'acecd5ea2924a4b900e7e149496e1f4b57976e51']
|
'acecd5ea2924a4b900e7e149496e1f4b57976e51']
|
||||||
|
|
||||||
|
REVLOGS = [
|
||||||
|
('J. David Ibañez', 'commit (initial): First commit'),
|
||||||
|
('J. David Ibañez', 'checkout: moving from master to i18n'),
|
||||||
|
('J. David Ibañez', 'commit: Say hello in Spanish'),
|
||||||
|
('J. David Ibañez', 'commit: Say hello in French'),
|
||||||
|
('J. David Ibañez', 'checkout: moving from i18n to master'),
|
||||||
|
('J. David Ibañez', 'commit: Add .gitignore file'),
|
||||||
|
('J. David Ibañez', 'merge i18n: Merge made by recursive.')
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class RevlogTestTest(utils.RepoTestCase):
|
||||||
|
def test_log(self):
|
||||||
|
ref = self.repo.lookup_reference('HEAD')
|
||||||
|
for i,entry in enumerate(ref.log()):
|
||||||
|
self.assertEqual(entry.committer.name, REVLOGS[i][0])
|
||||||
|
self.assertEqual(entry.message, REVLOGS[i][1])
|
||||||
|
|
||||||
class WalkerTest(utils.RepoTestCase):
|
class WalkerTest(utils.RepoTestCase):
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user