Synchronized with upstream
This commit is contained in:
commit
d054788d19
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 <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_patch(Diff *self);
|
||||
|
||||
|
@ -45,8 +45,7 @@ typedef struct {
|
||||
int new_start;
|
||||
int new_lines;
|
||||
char* new_file;
|
||||
PyObject *old_data;
|
||||
PyObject *new_data;
|
||||
PyObject *data;
|
||||
} Hunk;
|
||||
|
||||
typedef struct {
|
||||
@ -71,6 +70,23 @@ typedef struct {
|
||||
git_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 {
|
||||
PyObject_HEAD
|
||||
Object *obj;
|
||||
|
15
src/pygit2.c
15
src/pygit2.c
@ -53,6 +53,8 @@ PyTypeObject IndexEntryType;
|
||||
PyTypeObject IndexIterType;
|
||||
PyTypeObject WalkerType;
|
||||
PyTypeObject ReferenceType;
|
||||
PyTypeObject RefLogIterType;
|
||||
PyTypeObject RefLogEntryType;
|
||||
PyTypeObject SignatureType;
|
||||
|
||||
|
||||
@ -131,12 +133,6 @@ moduleinit(PyObject* m)
|
||||
CommitType.tp_base = &ObjectType;
|
||||
if (PyType_Ready(&CommitType) < 0)
|
||||
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;
|
||||
if (PyType_Ready(&TreeType) < 0)
|
||||
return NULL;
|
||||
@ -147,6 +143,11 @@ moduleinit(PyObject* m)
|
||||
if (PyType_Ready(&TagType) < 0)
|
||||
return NULL;
|
||||
|
||||
if (PyType_Ready(&DiffType) < 0)
|
||||
return NULL;
|
||||
if (PyType_Ready(&HunkType) < 0)
|
||||
return NULL;
|
||||
|
||||
TreeEntryType.tp_new = PyType_GenericNew;
|
||||
if (PyType_Ready(&TreeEntryType) < 0)
|
||||
return NULL;
|
||||
@ -165,6 +166,8 @@ moduleinit(PyObject* m)
|
||||
ReferenceType.tp_new = PyType_GenericNew;
|
||||
if (PyType_Ready(&ReferenceType) < 0)
|
||||
return NULL;
|
||||
if (PyType_Ready(&RefLogEntryType) < 0)
|
||||
return NULL;
|
||||
SignatureType.tp_new = PyType_GenericNew;
|
||||
if (PyType_Ready(&SignatureType) < 0)
|
||||
return NULL;
|
||||
|
@ -6,6 +6,10 @@
|
||||
#include <pygit2/utils.h>
|
||||
#include <pygit2/diff.h>
|
||||
|
||||
extern PyObject *GitError;
|
||||
|
||||
extern PyTypeObject TreeType;
|
||||
extern PyTypeObject IndexType;
|
||||
extern PyTypeObject DiffType;
|
||||
extern PyTypeObject HunkType;
|
||||
|
||||
@ -13,30 +17,31 @@ static int diff_data_cb(
|
||||
void *cb_data,
|
||||
git_diff_delta *delta,
|
||||
git_diff_range *range,
|
||||
char usage,
|
||||
const char *line,
|
||||
size_t line_len)
|
||||
char line_origin,
|
||||
const char *content,
|
||||
size_t content_len)
|
||||
{
|
||||
PyObject *hunks, *tmp;
|
||||
PyObject *hunks, *data, *tmp;
|
||||
Hunk *hunk;
|
||||
Py_ssize_t size;
|
||||
Py_ssize_t size;
|
||||
|
||||
hunks = PyDict_GetItemString(cb_data, "hunks");
|
||||
if(hunks == NULL)
|
||||
if (hunks == NULL)
|
||||
return -1;
|
||||
|
||||
size = PyList_Size(hunks);
|
||||
hunk = (Hunk*) PyList_GetItem(hunks, size-1);
|
||||
if(hunk == NULL)
|
||||
hunk = (Hunk *)PyList_GetItem(hunks, size - 1);
|
||||
if (hunk == NULL)
|
||||
return -1;
|
||||
|
||||
tmp = PyBytes_FromStringAndSize(line, line_len);
|
||||
tmp = PyBytes_FromStringAndSize(content, content_len);
|
||||
|
||||
if(usage != GIT_DIFF_LINE_DELETION)
|
||||
PyBytes_Concat(&hunk->new_data, tmp);
|
||||
data = Py_BuildValue("(O,i)",
|
||||
tmp,
|
||||
line_origin
|
||||
);
|
||||
|
||||
if(usage != GIT_DIFF_LINE_ADDITION)
|
||||
PyBytes_Concat(&hunk->old_data, tmp);
|
||||
PyList_Append(hunk->data, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -52,12 +57,14 @@ static int diff_hunk_cb(
|
||||
Hunk *hunk;
|
||||
|
||||
hunks = PyDict_GetItemString(cb_data, "hunks");
|
||||
if(hunks == NULL) {
|
||||
if (hunks == NULL) {
|
||||
hunks = PyList_New(0);
|
||||
PyDict_SetItemString(cb_data, "hunks", hunks);
|
||||
}
|
||||
|
||||
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_lines = range->old_lines;
|
||||
@ -67,25 +74,29 @@ static int diff_hunk_cb(
|
||||
int len;
|
||||
char* old_path, *new_path;
|
||||
|
||||
len = strlen(delta->old_file.path) + 1;
|
||||
old_path = malloc(sizeof(char) * len);
|
||||
memcpy(old_path, delta->old_file.path, len);
|
||||
hunk->old_file = old_path;
|
||||
if (delta->old_file.path != NULL) {
|
||||
len = strlen(delta->old_file.path) + 1;
|
||||
old_path = malloc(sizeof(char) * len);
|
||||
memcpy(old_path, delta->old_file.path, len);
|
||||
hunk->old_file = old_path;
|
||||
} else {
|
||||
hunk->old_file = "";
|
||||
}
|
||||
|
||||
len = strlen(delta->new_file.path) + 1;
|
||||
new_path = malloc(sizeof(char) * len);
|
||||
memcpy(new_path, delta->new_file.path, len);
|
||||
hunk->new_file = new_path;
|
||||
if (delta->new_file.path != NULL) {
|
||||
len = strlen(delta->new_file.path) + 1;
|
||||
new_path = malloc(sizeof(char) * len);
|
||||
memcpy(new_path, delta->new_file.path, len);
|
||||
hunk->new_file = new_path;
|
||||
} else {
|
||||
hunk->new_file = "";
|
||||
}
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
hunk->old_data = Py_BuildValue("y", "");
|
||||
hunk->new_data = Py_BuildValue("y", "");
|
||||
#else
|
||||
hunk->old_data = Py_BuildValue("s", "");
|
||||
hunk->new_data = Py_BuildValue("s", "");
|
||||
#endif
|
||||
if (hunk->data == NULL) {
|
||||
hunk->data = PyList_New(0);
|
||||
}
|
||||
|
||||
PyList_Append(hunks, (PyObject*) hunk);
|
||||
PyList_Append(hunks, (PyObject *)hunk);
|
||||
|
||||
return 0;
|
||||
};
|
||||
@ -94,20 +105,23 @@ static int diff_file_cb(void *cb_data, git_diff_delta *delta, float progress)
|
||||
{
|
||||
PyObject *files, *file;
|
||||
|
||||
files = PyDict_GetItemString(cb_data, "files");
|
||||
if(files == NULL) {
|
||||
files = PyList_New(0);
|
||||
PyDict_SetItemString(cb_data, "files", files);
|
||||
if(delta->old_file.path != NULL && delta->new_file.path != NULL) {
|
||||
files = PyDict_GetItemString(cb_data, "files");
|
||||
|
||||
if(files == NULL) {
|
||||
files = PyList_New(0);
|
||||
PyDict_SetItemString(cb_data, "files", files);
|
||||
}
|
||||
|
||||
file = Py_BuildValue("(s,s,i)",
|
||||
delta->old_file.path,
|
||||
delta->new_file.path,
|
||||
delta->status
|
||||
);
|
||||
|
||||
PyList_Append(files, file);
|
||||
}
|
||||
|
||||
file = Py_BuildValue("(s,s,i)",
|
||||
delta->old_file.path,
|
||||
delta->new_file.path,
|
||||
delta->status
|
||||
);
|
||||
|
||||
PyList_Append(files, file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -137,7 +151,7 @@ static int diff_print_cb(
|
||||
size_t line_len)
|
||||
{
|
||||
PyObject *data = PyBytes_FromStringAndSize(line, line_len);
|
||||
PyBytes_ConcatAndDel((PyObject**) cb_data, data);
|
||||
PyBytes_ConcatAndDel((PyObject **)cb_data, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -161,16 +175,10 @@ Hunk_init(Hunk *self, PyObject *args, PyObject *kwds)
|
||||
self->new_start = 0;
|
||||
self->new_lines = 0;
|
||||
|
||||
self->old_data = PyString_FromString("");
|
||||
if (self->old_data == NULL) {
|
||||
Py_DECREF(self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
self->new_data = PyString_FromString("");
|
||||
if (self->new_data == NULL) {
|
||||
Py_DECREF(self);
|
||||
return -1;
|
||||
self->data = PyList_New(0);
|
||||
if (self->data == NULL) {
|
||||
Py_XDECREF(self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -179,8 +187,7 @@ Hunk_init(Hunk *self, PyObject *args, PyObject *kwds)
|
||||
static void
|
||||
Hunk_dealloc(Hunk *self)
|
||||
{
|
||||
Py_XDECREF(self->old_data);
|
||||
Py_XDECREF(self->new_data);
|
||||
Py_XDECREF(self->data);
|
||||
PyObject_Del(self);
|
||||
}
|
||||
|
||||
@ -188,17 +195,16 @@ PyMemberDef Hunk_members[] = {
|
||||
{"old_start", T_INT, offsetof(Hunk, old_start), 0, "old start"},
|
||||
{"old_lines", T_INT, offsetof(Hunk, old_lines), 0, "old lines"},
|
||||
{"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_lines", T_INT, offsetof(Hunk, new_lines), 0, "new lines"},
|
||||
{"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}
|
||||
};
|
||||
|
||||
PyTypeObject HunkType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"pygit2.Hunk", /* tp_name */
|
||||
"_pygit2.Hunk", /* tp_name */
|
||||
sizeof(Hunk), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
(destructor)Hunk_dealloc, /* tp_dealloc */
|
||||
@ -277,7 +283,7 @@ static PyMethodDef Diff_methods[] = {
|
||||
|
||||
PyTypeObject DiffType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"pygit2.Diff", /* tp_name */
|
||||
"_pygit2.Diff", /* tp_name */
|
||||
sizeof(Diff), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
(destructor)Diff_dealloc, /* tp_dealloc */
|
||||
|
@ -33,16 +33,17 @@ PyObject * Error_type(int type)
|
||||
|
||||
// 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;
|
||||
if(error != NULL) {
|
||||
switch (error->klass) {
|
||||
case GITERR_NOMEMORY:
|
||||
return PyExc_MemoryError;
|
||||
case GITERR_OS:
|
||||
return PyExc_OSError;
|
||||
case GITERR_INVALID:
|
||||
return PyExc_ValueError;
|
||||
}
|
||||
}
|
||||
return GitError;
|
||||
}
|
||||
|
||||
|
||||
@ -51,10 +52,13 @@ PyObject* Error_set(int err)
|
||||
assert(err < 0);
|
||||
|
||||
if(err != GIT_ERROR) { //expected failure
|
||||
PyErr_SetNone(Error_type(err));
|
||||
PyErr_SetNone(Error_type(err));
|
||||
} else { //critical failure
|
||||
const git_error* error = giterr_last();
|
||||
PyErr_SetString(Error_type(err), error->message);
|
||||
const git_error* error = giterr_last();
|
||||
char* message = (error == NULL) ?
|
||||
"(No error information given)" : error->message;
|
||||
|
||||
PyErr_SetString(Error_type(err), message);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include <pygit2/index.h>
|
||||
|
||||
extern PyTypeObject IndexType;
|
||||
extern PyTypeObject TreeType;
|
||||
extern PyTypeObject DiffType;
|
||||
extern PyTypeObject IndexIterType;
|
||||
extern PyTypeObject IndexEntryType;
|
||||
|
||||
@ -74,6 +76,48 @@ Index_clear(Index *self)
|
||||
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 *
|
||||
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."},
|
||||
{"clear", (PyCFunction)Index_clear, METH_NOARGS,
|
||||
"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 the first index of any entries which point to given path in the"
|
||||
" Git index."},
|
||||
|
@ -1,12 +1,100 @@
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#include <Python.h>
|
||||
#include <string.h>
|
||||
#include <structmember.h>
|
||||
#include <pygit2/error.h>
|
||||
#include <pygit2/types.h>
|
||||
#include <pygit2/utils.h>
|
||||
#include <pygit2/oid.h>
|
||||
#include <pygit2/signature.h>
|
||||
#include <pygit2/reference.h>
|
||||
|
||||
|
||||
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
|
||||
Reference_dealloc(Reference *self)
|
||||
@ -221,6 +309,97 @@ Reference_get_type(Reference *self)
|
||||
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[] = {
|
||||
{"delete", (PyCFunction)Reference_delete, METH_NOARGS,
|
||||
"Delete this reference. It will no longer be valid!"},
|
||||
@ -230,6 +409,8 @@ PyMethodDef Reference_methods[] = {
|
||||
"Reload the reference from the file-system."},
|
||||
{"resolve", (PyCFunction)Reference_resolve, METH_NOARGS,
|
||||
"Resolve a symbolic reference and return a direct reference."},
|
||||
{"log", (PyCFunction)Reference_log, METH_NOARGS,
|
||||
"Retrieves the current reference log."},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
|
@ -15,6 +15,7 @@ extern PyTypeObject CommitType;
|
||||
extern PyTypeObject BlobType;
|
||||
extern PyTypeObject TagType;
|
||||
extern PyTypeObject TreeBuilderType;
|
||||
extern PyTypeObject DiffType;
|
||||
|
||||
git_otype
|
||||
int_to_loose_object_type(int type_id)
|
||||
|
@ -9,6 +9,7 @@
|
||||
extern PyTypeObject TreeType;
|
||||
extern PyTypeObject DiffType;
|
||||
extern PyTypeObject TreeIterType;
|
||||
extern PyTypeObject IndexType;
|
||||
|
||||
void
|
||||
TreeEntry_dealloc(TreeEntry *self)
|
||||
@ -236,19 +237,34 @@ Tree_diff_tree(Tree *self, PyObject *args)
|
||||
int err;
|
||||
|
||||
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;
|
||||
if (py_tree->repo->repo != self->repo->repo)
|
||||
return Error_set(GIT_ERROR);
|
||||
|
||||
err = git_diff_tree_to_tree(
|
||||
self->repo->repo,
|
||||
&opts,
|
||||
self->tree,
|
||||
py_tree->tree,
|
||||
&diff);
|
||||
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(
|
||||
self->repo->repo,
|
||||
&opts,
|
||||
self->tree,
|
||||
((Tree *)py_obj)->tree,
|
||||
&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)
|
||||
return Error_set(err);
|
||||
|
||||
@ -281,8 +297,14 @@ PyMappingMethods Tree_as_mapping = {
|
||||
};
|
||||
|
||||
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}
|
||||
};
|
||||
|
||||
|
@ -40,6 +40,7 @@ __author__ = 'Nico.Geyso@FU-Berlin.de (Nico von Geyso)'
|
||||
COMMIT_SHA1_1 = '5fe808e8953c12735680c257f56600cb0de44b10'
|
||||
COMMIT_SHA1_2 = 'c2792cfa289ae6321ecf2cd5806c2194b0fd070c'
|
||||
COMMIT_SHA1_3 = '2cdae28389c059815e951d0bb9eed6533f61a46b'
|
||||
|
||||
PATCH = b"""diff --git a/a b/a
|
||||
index 7f129fd..af431f2 100644
|
||||
--- a/a
|
||||
@ -56,6 +57,45 @@ index 297efb8..0000000
|
||||
-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):
|
||||
|
||||
@ -64,6 +104,14 @@ class DiffTest(utils.BareRepoTestCase):
|
||||
commit_b = self.repo[COMMIT_SHA1_2]
|
||||
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):
|
||||
commit_a = self.repo[COMMIT_SHA1_1]
|
||||
commit_b = self.repo[COMMIT_SHA1_2]
|
||||
@ -83,8 +131,8 @@ class DiffTest(utils.BareRepoTestCase):
|
||||
self.assertEqual(hunk.old_file, 'a')
|
||||
self.assertEqual(hunk.new_file, 'a')
|
||||
|
||||
self.assertEqual(hunk.old_data, b'a contents 2\n')
|
||||
self.assertEqual(hunk.new_data, b'a contents\n')
|
||||
#self.assertEqual(hunk.data[0][0], b'a contents 2\n')
|
||||
#self.assertEqual(hunk.data[1][0], b'a contents\n')
|
||||
|
||||
def test_diff_merge(self):
|
||||
commit_a = self.repo[COMMIT_SHA1_1]
|
||||
@ -113,8 +161,8 @@ class DiffTest(utils.BareRepoTestCase):
|
||||
self.assertEqual(hunk.old_file, 'b')
|
||||
self.assertEqual(hunk.new_file, 'b')
|
||||
|
||||
self.assertEqual(hunk.old_data, b'b contents\n')
|
||||
self.assertEqual(hunk.new_data, b'b contents 2\n')
|
||||
#self.assertEqual(hunk.data[0][0], b'b contents\n')
|
||||
#self.assertEqual(hunk.data[1][0], b'b contents 2\n')
|
||||
|
||||
def test_diff_patch(self):
|
||||
commit_a = self.repo[COMMIT_SHA1_1]
|
||||
|
@ -46,6 +46,23 @@ log = [
|
||||
'6aaa262e655dd54252e5813c8e5acd7780ed097d',
|
||||
'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):
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user