From a19a3d2515765b1170fa42753b3bf6a853dec35e Mon Sep 17 00:00:00 2001 From: Nico von Geyso <Nico.Geyso@FU-Berlin.de> Date: Mon, 4 Mar 2013 10:39:44 +0100 Subject: [PATCH] diff - use old fashioned iterators instead of callback based ones --- include/pygit2/types.h | 10 +- src/diff.c | 281 +++++++++++++++-------------------------- src/pygit2.c | 7 - test/test_diff.py | 2 +- 4 files changed, 107 insertions(+), 193 deletions(-) diff --git a/include/pygit2/types.h b/include/pygit2/types.h index 9c8a429..7625b89 100644 --- a/include/pygit2/types.h +++ b/include/pygit2/types.h @@ -76,17 +76,17 @@ typedef struct { typedef struct { PyObject_HEAD - char *header; + const char *header; int old_start; int old_lines; - PyObject *old_oid; + char* old_oid; int old_mode; - char* old_file; + const char* old_file; int new_start; int new_lines; - PyObject *new_oid; + char* new_oid; int new_mode; - char* new_file; + const char* new_file; PyObject *data; } Hunk; diff --git a/src/diff.c b/src/diff.c index 50f3b51..7440013 100644 --- a/src/diff.c +++ b/src/diff.c @@ -40,204 +40,125 @@ extern PyTypeObject IndexType; extern PyTypeObject DiffType; extern PyTypeObject HunkType; -static int diff_data_cb( - const git_diff_delta *delta, - const git_diff_range *range, - char line_origin, - const char *content, - size_t content_len, - void *cb_data) -{ - PyObject *hunks, *data; - Hunk *hunk; - Py_ssize_t size; - - hunks = PyDict_GetItemString(cb_data, "hunks"); - if (hunks == NULL) - return -1; - - size = PyList_Size(hunks); - hunk = (Hunk *)PyList_GetItem(hunks, size - 1); - if (hunk == NULL) - return -1; - - data = Py_BuildValue("(s#,i)", - content, content_len, - line_origin - ); - PyList_Append(hunk->data, data); - Py_DECREF(data); - - return 0; -} - -static int diff_hunk_cb( - const git_diff_delta *delta, - const git_diff_range *range, - const char *header, - size_t header_len, - void *cb_data) -{ - PyObject *hunks; - Hunk *hunk; - int len; - char* old_path = NULL, *new_path = NULL; - char oid[GIT_OID_HEXSZ]; - - - hunks = PyDict_GetItemString(cb_data, "hunks"); - if (hunks == NULL) { - hunks = PyList_New(0); - PyDict_SetItemString(cb_data, "hunks", hunks); - Py_DECREF(hunks); - } - - hunk = (Hunk*)PyType_GenericNew(&HunkType, NULL, NULL); - if (hunk == NULL) - return -1; - - hunk->old_start = range->old_start; - hunk->old_lines = range->old_lines; - hunk->new_start = range->new_start; - hunk->new_lines = range->new_lines; - - hunk->old_mode = delta->old_file.mode; - hunk->new_mode = delta->new_file.mode; - - git_oid_fmt(oid, &delta->old_file.oid); - hunk->old_oid = PyUnicode_FromStringAndSize(oid, GIT_OID_HEXSZ); - git_oid_fmt(oid, &delta->new_file.oid); - hunk->new_oid = PyUnicode_FromStringAndSize(oid, GIT_OID_HEXSZ); - - if (header) { - hunk->header = malloc(header_len+1); - - if (hunk->header == NULL) - return -1; - - memcpy(hunk->header, header, header_len); - hunk->header[header_len] = '\0'; - } - - if (delta->old_file.path != NULL) { - len = strlen(delta->old_file.path) + 1; - old_path = malloc(sizeof(char) * len); - if (old_path == NULL) { - free(hunk->header); - hunk->header = NULL; - return -1; - } - - memcpy(old_path, delta->old_file.path, len); - hunk->old_file = old_path; - } else { - hunk->old_file = ""; - } - - if (delta->new_file.path != NULL) { - len = strlen(delta->new_file.path) + 1; - new_path = malloc(sizeof(char) * len); - if (new_path == NULL) { - free(hunk->header); - free(old_path); - return -1; - } - - memcpy(new_path, delta->new_file.path, len); - hunk->new_file = new_path; - } else { - hunk->new_file = ""; - } - - if (hunk->data == NULL) - hunk->data = PyList_New(0); - - if (PyList_Append(hunks, (PyObject *)hunk) == 0) { - Py_DECREF(hunk); - } - else { - return -1; - } - - return 0; -}; - -static int -diff_file_cb(const git_diff_delta *delta, float progress, void *cb_data) -{ - PyObject *files, *file; - - 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); - Py_DECREF(files); - } - - file = Py_BuildValue("(s,s,i,i)", - delta->old_file.path, - delta->new_file.path, - delta->status, - delta->similarity - ); - - /* If success */ - if (PyList_Append(files, file) == 0) - Py_DECREF(file); - } - - return 0; -} - PyDoc_STRVAR(Diff_changes__doc__, "Raw changes."); PyObject * Diff_changes__get__(Diff *self) { + const git_diff_delta* delta; + const git_diff_range* range; + git_diff_patch* patch; + char buffer[41]; + const char* hunk_content; + size_t amounts, hunk_amounts, i, j, hunk_header_len, hunk_lines; + PyObject *file, *files, *hunks; + Hunk *py_hunk; + int err; if (self->diff_changes == NULL) { self->diff_changes = PyDict_New(); - git_diff_foreach( - self->diff, - &diff_file_cb, - &diff_hunk_cb, - &diff_data_cb, - self->diff_changes - ); + files = PyList_New(0); + PyDict_SetItemString(self->diff_changes, "files", files); + + hunks = PyList_New(0); + PyDict_SetItemString(self->diff_changes, "hunks", hunks); + + amounts = git_diff_num_deltas(self->diff); + for (i = 0; i < amounts ; ++i) { + err = git_diff_get_patch(&patch, &delta, self->diff, i); + + if (err == GIT_OK) { + file = Py_BuildValue("(s,s,i,i)", + delta->old_file.path, + delta->new_file.path, + delta->status, + delta->similarity + ); + + PyList_Append(files, file); + } + + hunk_amounts = git_diff_patch_num_hunks(patch); + + for (j=0; j < hunk_amounts; ++j) { + err = git_diff_patch_get_hunk(&range, &hunk_content, + &hunk_header_len, &hunk_lines, patch, j); + + if (err == GIT_OK) { + py_hunk = (Hunk*)PyType_GenericNew(&HunkType, NULL, NULL); + if (py_hunk != NULL) { + py_hunk->old_file = delta->old_file.path; + py_hunk->new_file = delta->new_file.path; + py_hunk->header = hunk_content; + py_hunk->old_start = range->old_start; + py_hunk->old_lines = range->old_lines; + py_hunk->new_start = range->new_start; + py_hunk->new_lines = range->new_lines; + + git_oid_fmt(buffer, &delta->old_file.oid); + py_hunk->old_oid = calloc(41, sizeof(char)); + memcpy(py_hunk->old_oid, buffer, 40); + + git_oid_fmt(buffer, &delta->new_file.oid); + py_hunk->new_oid = calloc(41, sizeof(char)); + memcpy(py_hunk->new_oid, buffer, 40); + + py_hunk->data = Py_BuildValue("(s#,i)", + hunk_content, hunk_header_len, + hunk_lines); + PyList_Append(hunks, (PyObject*) py_hunk); + } + } + } + } } return PyDict_Copy(self->diff_changes); } -static int diff_print_cb( - const git_diff_delta *delta, - const git_diff_range *range, - char usage, - const char *line, - size_t line_len, - void *cb_data) -{ - PyObject *data = PyBytes_FromStringAndSize(line, line_len); - PyBytes_ConcatAndDel((PyObject **)cb_data, data); - - return 0; -} - PyDoc_STRVAR(Diff_patch__doc__, "Patch."); PyObject * Diff_patch__get__(Diff *self) { - PyObject *patch = PyBytes_FromString(""); + const git_diff_delta* delta; + git_diff_patch* patch; + char* str = NULL, *buffer = NULL; + int err; + size_t i, len, num, size; + PyObject *py_patch; - git_diff_print_patch(self->diff, &diff_print_cb, (void*) &patch); + num = git_diff_num_deltas(self->diff); + for (i = 0; i < num ; ++i) { + err = git_diff_get_patch(&patch, &delta, self->diff, i); - return patch; + if (err < 0 || git_diff_patch_to_str(&str, patch) < 0) + return Error_set(err); + + len = strlen(str) + 1; + size = (buffer == NULL) ? len : strlen(buffer) + len; + buffer = realloc(buffer, size * sizeof(char)); + + if (len == size) + strcpy(buffer, str); + else + strcat(buffer, str); + + free(str); + } + + py_patch = PyUnicode_FromString(buffer); + + if (buffer != NULL) + free(buffer); + + if (patch != NULL) + git_diff_patch_free; + + return py_patch; } static int @@ -269,13 +190,13 @@ static void Hunk_dealloc(Hunk *self) { if (self->header != NULL) { - free(self->header); + free((void*) self->header); } if (self->new_file != NULL) { - free(self->new_file); + free((void*) self->new_file); } if (self->old_file != NULL) { - free(self->old_file); + free((void*) self->old_file); } Py_XDECREF(self->old_oid); Py_XDECREF(self->new_oid); @@ -289,12 +210,12 @@ PyMemberDef Hunk_members[] = { MEMBER(Hunk, old_lines, T_INT, "Old lines."), MEMBER(Hunk, old_mode, T_INT, "Old mode."), MEMBER(Hunk, old_file, T_STRING, "Old file."), - MEMBER(Hunk, old_oid, T_OBJECT, "Old oid."), + MEMBER(Hunk, old_oid, T_STRING, "Old oid."), MEMBER(Hunk, new_start, T_INT, "New start."), MEMBER(Hunk, new_lines, T_INT, "New lines."), MEMBER(Hunk, new_mode, T_INT, "New mode."), MEMBER(Hunk, new_file, T_STRING, "New file."), - MEMBER(Hunk, new_oid, T_OBJECT, "New oid."), + MEMBER(Hunk, new_oid, T_STRING, "New oid."), MEMBER(Hunk, data, T_OBJECT, "Data."), {NULL} }; diff --git a/src/pygit2.c b/src/pygit2.c index 6727e65..f2acbf0 100644 --- a/src/pygit2.c +++ b/src/pygit2.c @@ -343,13 +343,6 @@ moduleinit(PyObject* m) PyModule_AddIntConstant(m, "GIT_DIFF_FIND_AND_BREAK_REWRITES", GIT_DIFF_FIND_AND_BREAK_REWRITES); - /* Flags for diffed files */ - PyModule_AddIntConstant(m, "GIT_DIFF_FLAG_BINARY", GIT_DIFF_FLAG_BINARY); - PyModule_AddIntConstant(m, "GIT_DIFF_FLAG_NOT_BINARY", - GIT_DIFF_FLAG_NOT_BINARY); - PyModule_AddIntConstant(m, "GIT_DIFF_FLAG_VALID_OID", - GIT_DIFF_FLAG_VALID_OID); - /* Flags for diff deltas */ PyModule_AddIntConstant(m, "GIT_DELTA_UNMODIFIED", GIT_DELTA_UNMODIFIED); PyModule_AddIntConstant(m, "GIT_DELTA_ADDED", GIT_DELTA_ADDED); diff --git a/test/test_diff.py b/test/test_diff.py index ff3a54c..03f49e5 100644 --- a/test/test_diff.py +++ b/test/test_diff.py @@ -41,7 +41,7 @@ COMMIT_SHA1_3 = '2cdae28389c059815e951d0bb9eed6533f61a46b' COMMIT_SHA1_4 = 'ccca47fbb26183e71a7a46d165299b84e2e6c0b3' COMMIT_SHA1_5 = '056e626e51b1fc1ee2182800e399ed8d84c8f082' -PATCH = b"""diff --git a/a b/a +PATCH = """diff --git a/a b/a index 7f129fd..af431f2 100644 --- a/a +++ b/a