New DiffLine

Comes from PR #346

One difference, DiffLine.origin is a T_CHAR instead of T_OBJECT
This commit is contained in:
J. David Ibáñez 2015-02-12 16:56:34 +01:00
parent 7130df3a5e
commit 3d896769d0
7 changed files with 112 additions and 16 deletions

@ -36,12 +36,11 @@ Changelog
- New ``iter(pygit2.Blame)``
- New ``pygit2.DiffDelta`` and ``pygit2.DiffFile``
- New ``pygit2.DiffDelta``, ``pygit2.DiffFile`` and ``pygit.DiffLine``
- Rename ``pygit2.Hunk`` to ``pygit2.DiffHunk``
API changes::
API changes, translation table::
Hunk => DiffHunk
Patch.old_file_path => Patch.delta.old_file.path
Patch.new_file_path => Patch.delta.new_file.path
Patch.old_id => Patch.delta.old_file.id
@ -52,6 +51,10 @@ API changes::
Patch.additions => Patch.line_stats[1]
Patch.deletions => Patch.line_stats[2]
API changes, more:
- ``DiffHunk.lines`` is now a list of ``DiffLine`` objects, not tuples
0.22.0 (2015-01-16)
-------------------

@ -43,6 +43,7 @@ extern PyTypeObject DiffType;
extern PyTypeObject DiffDeltaType;
extern PyTypeObject DiffFileType;
extern PyTypeObject DiffHunkType;
extern PyTypeObject DiffLineType;
extern PyTypeObject RepositoryType;
PyObject *
@ -98,6 +99,25 @@ wrap_diff_delta(const git_diff_delta *delta)
return (PyObject *) py_delta;
}
PyObject *
wrap_diff_line(const git_diff_line *line)
{
DiffLine *py_line;
py_line = PyObject_New(DiffLine, &DiffLineType);
if (py_line) {
py_line->origin = line->origin;
py_line->old_lineno = line->old_lineno;
py_line->new_lineno = line->new_lineno;
py_line->num_lines = line->num_lines;
py_line->content = to_unicode_n(line->content, line->content_len,
NULL, NULL);
py_line->content_offset = line->content_offset;
}
return (PyObject *) py_line;
}
static void
DiffFile_dealloc(DiffFile *self)
{
@ -234,6 +254,70 @@ PyTypeObject DiffDeltaType = {
0, /* tp_new */
};
static void
DiffLine_dealloc(DiffLine *self)
{
Py_CLEAR(self->content);
PyObject_Del(self);
}
PyMemberDef DiffLine_members[] = {
MEMBER(DiffLine, origin, T_CHAR, "Type of the diff line"),
MEMBER(DiffLine, old_lineno, T_INT,
"Line number in old file or -1 for added line"),
MEMBER(DiffLine, new_lineno, T_INT,
"Line number in new file or -1 for deleted line"),
MEMBER(DiffLine, num_lines, T_INT,
"Number of newline characters in content"),
MEMBER(DiffLine, content_offset, T_INT,
"Offset in the original file to the content"),
MEMBER(DiffLine, content, T_OBJECT, "Content of the diff line"),
{NULL}
};
PyDoc_STRVAR(DiffLine__doc__, "DiffLine object.");
PyTypeObject DiffLineType = {
PyVarObject_HEAD_INIT(NULL, 0)
"_pygit2.DiffLine", /* tp_name */
sizeof(DiffLine), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)DiffLine_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 */
DiffLine__doc__, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
DiffLine_members, /* 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 */
};
PyObject *
diff_get_patch_byindex(git_diff *diff, size_t idx)
{

@ -37,7 +37,8 @@ PyObject* Diff_changes(Diff *self);
PyObject* Diff_patch(Diff *self);
PyObject* wrap_diff(git_diff *diff, Repository *repo);
PyObject* wrap_diff_file(const git_diff_file *file);
PyObject* wrap_diff_delta(const git_diff_delta *delta);
PyObject* wrap_diff_file(const git_diff_file *file);
PyObject* wrap_diff_line(const git_diff_line *line);
#endif

@ -76,21 +76,17 @@ wrap_patch(git_patch *patch)
py_hunk->lines = PyList_New(lines_in_hunk);
for (j = 0; j < lines_in_hunk; ++j) {
PyObject *py_line_origin = NULL, *py_line = NULL;
PyObject *py_line = NULL;
err = git_patch_get_line_in_hunk(&line, patch, i, j);
if (err < 0)
return Error_set(err);
py_line_origin = to_unicode_n(&line->origin, 1,
NULL, NULL);
py_line = to_unicode_n(line->content, line->content_len,
NULL, NULL);
PyList_SetItem(py_hunk->lines, j,
Py_BuildValue("OO", py_line_origin, py_line));
py_line = wrap_diff_line(line);
if (py_line == NULL)
return NULL;
Py_DECREF(py_line_origin);
Py_DECREF(py_line);
PyList_SetItem(py_hunk->lines, j, py_line);
}
PyList_SetItem((PyObject*) py_patch->hunks, i,

@ -47,6 +47,7 @@ extern PyTypeObject DiffIterType;
extern PyTypeObject DiffDeltaType;
extern PyTypeObject DiffFileType;
extern PyTypeObject DiffHunkType;
extern PyTypeObject DiffLineType;
extern PyTypeObject PatchType;
extern PyTypeObject TreeType;
extern PyTypeObject TreeBuilderType;
@ -292,11 +293,13 @@ moduleinit(PyObject* m)
INIT_TYPE(DiffDeltaType, NULL, NULL)
INIT_TYPE(DiffFileType, NULL, NULL)
INIT_TYPE(DiffHunkType, NULL, NULL)
INIT_TYPE(DiffLineType, NULL, NULL)
INIT_TYPE(PatchType, NULL, NULL)
ADD_TYPE(m, Diff)
ADD_TYPE(m, DiffDelta)
ADD_TYPE(m, DiffFile)
ADD_TYPE(m, DiffHunk)
ADD_TYPE(m, DiffLine)
ADD_TYPE(m, Patch)
ADD_CONSTANT_INT(m, GIT_DIFF_NORMAL)
ADD_CONSTANT_INT(m, GIT_DIFF_REVERSE)

@ -132,6 +132,15 @@ typedef struct {
int new_lines;
} DiffHunk;
typedef struct {
PyObject_HEAD
char origin;
int old_lineno;
int new_lineno;
int num_lines;
git_off_t content_offset;
PyObject *content;
} DiffLine;
/* git_tree_walk , git_treebuilder*/
SIMPLE_TYPE(TreeBuilder, git_treebuilder, bld)

@ -188,7 +188,7 @@ class DiffTest(utils.BareRepoTestCase):
def get_context_for_lines(diff):
hunks = chain(*map(lambda x: x.hunks, [p for p in diff]))
lines = chain(*map(lambda x: x.lines, hunks))
return map(lambda x: x[0], lines)
return map(lambda x: x.origin, lines)
entries = [p.delta.new_file.path for p in diff]
self.assertAll(lambda x: commit_a.tree[x], entries)
@ -271,7 +271,7 @@ class DiffTest(utils.BareRepoTestCase):
commit_b = self.repo[COMMIT_SHA1_2]
patch = commit_a.tree.diff_to_tree(commit_b.tree)[0]
hunk = patch.hunks[0]
lines = ('{0} {1}'.format(*x) for x in hunk.lines)
lines = ('{0} {1}'.format(x.origin, x.content) for x in hunk.lines)
self.assertEqual(HUNK_EXPECTED, ''.join(lines))
def test_find_similar(self):