/* * call-seq: * patch.delta -> delta * * Returns the delta object associated with the patch. */ static VALUE rb_git_diff_patch_delta(VALUE self) { git_patch *patch; Data_Get_Struct(self, git_patch, patch); return rugged_diff_delta_new(rugged_owner(self), git_patch_get_delta(patch)); }
/** * ggit_patch_get_delta: * @patch: a #GgitPatch. * * Get the diff delta corresponding to the patch. * * Returns: (transfer full): the #GgitDiffDelta of the patch. */ GgitDiffDelta * ggit_patch_get_delta (GgitPatch *patch) { g_return_val_if_fail (patch != NULL, NULL); return _ggit_diff_delta_wrap (git_patch_get_delta (patch->patch)); }
static void assert_patch_matches_blobs( git_patch *p, git_blob *a, git_blob *b, int hunks, int l0, int l1, int ctxt, int adds, int dels) { const git_diff_delta *delta; size_t tc, ta, td; cl_assert(p != NULL); delta = git_patch_get_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status); cl_assert_equal_oid(git_blob_id(a), &delta->old_file.id); cl_assert_equal_sz(git_blob_rawsize(a), delta->old_file.size); cl_assert_equal_oid(git_blob_id(b), &delta->new_file.id); cl_assert_equal_sz(git_blob_rawsize(b), delta->new_file.size); cl_assert_equal_i(hunks, (int)git_patch_num_hunks(p)); if (hunks > 0) cl_assert_equal_i(l0, git_patch_num_lines_in_hunk(p, 0)); if (hunks > 1) cl_assert_equal_i(l1, git_patch_num_lines_in_hunk(p, 1)); cl_git_pass(git_patch_line_stats(&tc, &ta, &td, p)); cl_assert_equal_i(ctxt, (int)tc); cl_assert_equal_i(adds, (int)ta); cl_assert_equal_i(dels, (int)td); }
void test_diff_blob__can_compare_identical_blobs_with_patch(void) { git_patch *p; const git_diff_delta *delta; cl_git_pass(git_patch_from_blobs(&p, d, NULL, d, NULL, &opts)); cl_assert(p != NULL); delta = git_patch_get_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_UNMODIFIED, delta->status); cl_assert_equal_sz(delta->old_file.size, git_blob_rawsize(d)); cl_assert_equal_oid(git_blob_id(d), &delta->old_file.id); cl_assert_equal_sz(delta->new_file.size, git_blob_rawsize(d)); cl_assert_equal_oid(git_blob_id(d), &delta->new_file.id); cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); git_patch_free(p); cl_git_pass(git_patch_from_blobs(&p, NULL, NULL, NULL, NULL, &opts)); cl_assert(p != NULL); delta = git_patch_get_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_UNMODIFIED, delta->status); cl_assert_equal_sz(0, delta->old_file.size); cl_assert(git_oid_iszero(&delta->old_file.id)); cl_assert_equal_sz(0, delta->new_file.size); cl_assert(git_oid_iszero(&delta->new_file.id)); cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); git_patch_free(p); cl_git_pass(git_patch_from_blobs(&p, alien, NULL, alien, NULL, &opts)); cl_assert(p != NULL); cl_assert_equal_i(GIT_DELTA_UNMODIFIED, git_patch_get_delta(p)->status); cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); git_patch_free(p); }
PyObject * wrap_patch(git_patch *patch) { Patch *py_patch; if (!patch) Py_RETURN_NONE; py_patch = PyObject_New(Patch, &PatchType); if (py_patch) { size_t i, j, hunk_amounts, lines_in_hunk, additions, deletions; const git_diff_delta *delta; const git_diff_hunk *hunk; const git_diff_line *line; int err; delta = git_patch_get_delta(patch); py_patch->old_file_path = delta->old_file.path; py_patch->new_file_path = delta->new_file.path; py_patch->status = git_diff_status_char(delta->status); py_patch->similarity = delta->similarity; py_patch->flags = delta->flags; py_patch->old_id = git_oid_allocfmt(&delta->old_file.id); py_patch->new_id = git_oid_allocfmt(&delta->new_file.id); git_patch_line_stats(NULL, &additions, &deletions, patch); py_patch->additions = additions; py_patch->deletions = deletions; hunk_amounts = git_patch_num_hunks(patch); py_patch->hunks = PyList_New(hunk_amounts); for (i = 0; i < hunk_amounts; ++i) { Hunk *py_hunk = NULL; err = git_patch_get_hunk(&hunk, &lines_in_hunk, patch, i); if (err < 0) return Error_set(err); py_hunk = PyObject_New(Hunk, &HunkType); if (py_hunk != NULL) { py_hunk->old_start = hunk->old_start; py_hunk->old_lines = hunk->old_lines; py_hunk->new_start = hunk->new_start; py_hunk->new_lines = hunk->new_lines; py_hunk->lines = PyList_New(lines_in_hunk); for (j = 0; j < lines_in_hunk; ++j) { PyObject *py_line_origin = NULL, *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_DECREF(py_line_origin); Py_DECREF(py_line); } PyList_SetItem((PyObject*) py_patch->hunks, i, (PyObject*) py_hunk); } } } git_patch_free(patch); return (PyObject*) py_patch; }
int diff_foreach_via_iterator( git_diff *diff, git_diff_file_cb file_cb, git_diff_hunk_cb hunk_cb, git_diff_line_cb line_cb, void *data) { size_t d, num_d = git_diff_num_deltas(diff); for (d = 0; d < num_d; ++d) { git_patch *patch; const git_diff_delta *delta; size_t h, num_h; cl_git_pass(git_patch_from_diff(&patch, diff, d)); cl_assert((delta = git_patch_get_delta(patch)) != NULL); /* call file_cb for this file */ if (file_cb != NULL && file_cb(delta, (float)d / num_d, data) != 0) { git_patch_free(patch); goto abort; } /* if there are no changes, then the patch will be NULL */ if (!patch) { cl_assert(delta->status == GIT_DELTA_UNMODIFIED || (delta->flags & GIT_DIFF_FLAG_BINARY) != 0); continue; } if (!hunk_cb && !line_cb) { git_patch_free(patch); continue; } num_h = git_patch_num_hunks(patch); for (h = 0; h < num_h; h++) { const git_diff_hunk *hunk; size_t l, num_l; cl_git_pass(git_patch_get_hunk(&hunk, &num_l, patch, h)); if (hunk_cb && hunk_cb(delta, hunk, data) != 0) { git_patch_free(patch); goto abort; } for (l = 0; l < num_l; ++l) { const git_diff_line *line; cl_git_pass(git_patch_get_line_in_hunk(&line, patch, h, l)); if (line_cb && line_cb(delta, hunk, line, data) != 0) { git_patch_free(patch); goto abort; } } } git_patch_free(patch); } return 0; abort: giterr_clear(); return GIT_EUSER; }
int git_diff_get_stats( git_diff_stats **out, git_diff *diff) { size_t i, deltas; size_t total_insertions = 0, total_deletions = 0; git_diff_stats *stats = NULL; int error = 0; assert(out && diff); stats = (git_diff_stats *) git__calloc(1, sizeof(git_diff_stats)); GITERR_CHECK_ALLOC(stats); deltas = git_diff_num_deltas(diff); stats->filestats = (diff_file_stats *) git__calloc(deltas, sizeof(diff_file_stats)); if (!stats->filestats) { git__free(stats); return -1; } stats->diff = diff; GIT_REFCOUNT_INC(diff); for (i = 0; i < deltas && !error; ++i) { git_patch *patch = NULL; size_t add = 0, remove = 0, namelen; const git_diff_delta *delta; if ((error = git_patch_from_diff(&patch, diff, i)) < 0) break; /* keep a count of renames because it will affect formatting */ delta = git_patch_get_delta(patch); namelen = strlen(delta->new_file.path); if (strcmp(delta->old_file.path, delta->new_file.path) != 0) { namelen += strlen(delta->old_file.path); stats->renames++; } /* and, of course, count the line stats */ error = git_patch_line_stats(NULL, &add, &remove, patch); git_patch_free(patch); stats->filestats[i].insertions = add; stats->filestats[i].deletions = remove; total_insertions += add; total_deletions += remove; if (stats->max_name < namelen) stats->max_name = namelen; if (stats->max_filestat < add + remove) stats->max_filestat = add + remove; } stats->files_changed = deltas; stats->insertions = total_insertions; stats->deletions = total_deletions; stats->max_digits = digits_for_value(stats->max_filestat + 1); if (error < 0) { git_diff_stats_free(stats); stats = NULL; } *out = stats; return error; }
static int git_xdiff_cb(void *priv, mmbuffer_t *bufs, int len) { git_xdiff_info *info = priv; git_patch *patch = info->patch; const git_diff_delta *delta = git_patch_get_delta(patch); git_diff_output *output = &info->xo->output; git_diff_line line; if (len == 1) { output->error = git_xdiff_parse_hunk(&info->hunk, bufs[0].ptr); if (output->error < 0) return output->error; info->hunk.header_len = bufs[0].size; if (info->hunk.header_len >= sizeof(info->hunk.header)) info->hunk.header_len = sizeof(info->hunk.header) - 1; memcpy(info->hunk.header, bufs[0].ptr, info->hunk.header_len); info->hunk.header[info->hunk.header_len] = '\0'; if (output->hunk_cb != NULL && output->hunk_cb(delta, &info->hunk, output->payload)) output->error = GIT_EUSER; info->old_lineno = info->hunk.old_start; info->new_lineno = info->hunk.new_start; } if (len == 2 || len == 3) { /* expect " "/"-"/"+", then data */ line.origin = (*bufs[0].ptr == '+') ? GIT_DIFF_LINE_ADDITION : (*bufs[0].ptr == '-') ? GIT_DIFF_LINE_DELETION : GIT_DIFF_LINE_CONTEXT; if (line.origin == GIT_DIFF_LINE_ADDITION) line.content_offset = bufs[1].ptr - info->xd_new_data.ptr; else if (line.origin == GIT_DIFF_LINE_DELETION) line.content_offset = bufs[1].ptr - info->xd_old_data.ptr; else line.content_offset = -1; output->error = diff_update_lines( info, &line, bufs[1].ptr, bufs[1].size); if (!output->error && output->data_cb != NULL && output->data_cb(delta, &info->hunk, &line, output->payload)) output->error = GIT_EUSER; } if (len == 3 && !output->error) { /* If we have a '+' and a third buf, then we have added a line * without a newline and the old code had one, so DEL_EOFNL. * If we have a '-' and a third buf, then we have removed a line * with out a newline but added a blank line, so ADD_EOFNL. */ line.origin = (*bufs[0].ptr == '+') ? GIT_DIFF_LINE_DEL_EOFNL : (*bufs[0].ptr == '-') ? GIT_DIFF_LINE_ADD_EOFNL : GIT_DIFF_LINE_CONTEXT_EOFNL; line.content_offset = -1; output->error = diff_update_lines( info, &line, bufs[2].ptr, bufs[2].size); if (!output->error && output->data_cb != NULL && output->data_cb(delta, &info->hunk, &line, output->payload)) output->error = GIT_EUSER; } return output->error; }
void test_diff_blob__can_compare_blob_to_buffer_with_patch(void) { git_patch *p; git_blob *a; git_oid a_oid; const char *a_content = "Hello from the root\n"; const char *b_content = "Hello from the root\n\nSome additional lines\n\nDown here below\n\n"; size_t tc, ta, td; /* tests/resources/attr/root_test1 */ cl_git_pass(git_oid_fromstrn(&a_oid, "45141a79", 8)); cl_git_pass(git_blob_lookup_prefix(&a, g_repo, &a_oid, 8)); /* diff from blob a to content of b */ cl_git_pass(git_patch_from_blob_and_buffer( &p, a, NULL, b_content, strlen(b_content), NULL, &opts)); cl_assert(p != NULL); cl_assert_equal_i(GIT_DELTA_MODIFIED, git_patch_get_delta(p)->status); cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); cl_assert_equal_i(6, git_patch_num_lines_in_hunk(p, 0)); cl_git_pass(git_patch_line_stats(&tc, &ta, &td, p)); cl_assert_equal_i(1, (int)tc); cl_assert_equal_i(5, (int)ta); cl_assert_equal_i(0, (int)td); git_patch_free(p); /* diff from blob a to content of a */ opts.flags |= GIT_DIFF_INCLUDE_UNMODIFIED; cl_git_pass(git_patch_from_blob_and_buffer( &p, a, NULL, a_content, strlen(a_content), NULL, &opts)); cl_assert(p != NULL); cl_assert_equal_i(GIT_DELTA_UNMODIFIED, git_patch_get_delta(p)->status); cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); git_patch_free(p); /* diff from NULL blob to content of a */ cl_git_pass(git_patch_from_blob_and_buffer( &p, NULL, NULL, a_content, strlen(a_content), NULL, &opts)); cl_assert(p != NULL); cl_assert_equal_i(GIT_DELTA_ADDED, git_patch_get_delta(p)->status); cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); cl_assert_equal_i(1, git_patch_num_lines_in_hunk(p, 0)); git_patch_free(p); /* diff from blob a to NULL buffer */ cl_git_pass(git_patch_from_blob_and_buffer( &p, a, NULL, NULL, 0, NULL, &opts)); cl_assert(p != NULL); cl_assert_equal_i(GIT_DELTA_DELETED, git_patch_get_delta(p)->status); cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); cl_assert_equal_i(1, git_patch_num_lines_in_hunk(p, 0)); git_patch_free(p); /* diff with reverse */ opts.flags ^= GIT_DIFF_REVERSE; cl_git_pass(git_patch_from_blob_and_buffer( &p, a, NULL, NULL, 0, NULL, &opts)); cl_assert(p != NULL); cl_assert_equal_i(GIT_DELTA_ADDED, git_patch_get_delta(p)->status); cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); cl_assert_equal_i(1, git_patch_num_lines_in_hunk(p, 0)); git_patch_free(p); git_blob_free(a); }
void test_diff_blob__can_compare_against_null_blobs_with_patch(void) { git_blob *e = NULL; git_patch *p; const git_diff_delta *delta; const git_diff_line *line; int l, max_l; cl_git_pass(git_patch_from_blobs(&p, d, NULL, e, NULL, &opts)); cl_assert(p != NULL); delta = git_patch_get_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_DELETED, delta->status); cl_assert_equal_oid(git_blob_id(d), &delta->old_file.id); cl_assert_equal_sz(git_blob_rawsize(d), delta->old_file.size); cl_assert(git_oid_iszero(&delta->new_file.id)); cl_assert_equal_sz(0, delta->new_file.size); cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); cl_assert_equal_i(14, git_patch_num_lines_in_hunk(p, 0)); max_l = git_patch_num_lines_in_hunk(p, 0); for (l = 0; l < max_l; ++l) { cl_git_pass(git_patch_get_line_in_hunk(&line, p, 0, l)); cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin); } git_patch_free(p); opts.flags |= GIT_DIFF_REVERSE; cl_git_pass(git_patch_from_blobs(&p, d, NULL, e, NULL, &opts)); cl_assert(p != NULL); delta = git_patch_get_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_ADDED, delta->status); cl_assert(git_oid_iszero(&delta->old_file.id)); cl_assert_equal_sz(0, delta->old_file.size); cl_assert_equal_oid(git_blob_id(d), &delta->new_file.id); cl_assert_equal_sz(git_blob_rawsize(d), delta->new_file.size); cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); cl_assert_equal_i(14, git_patch_num_lines_in_hunk(p, 0)); max_l = git_patch_num_lines_in_hunk(p, 0); for (l = 0; l < max_l; ++l) { cl_git_pass(git_patch_get_line_in_hunk(&line, p, 0, l)); cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin); } git_patch_free(p); opts.flags ^= GIT_DIFF_REVERSE; cl_git_pass(git_patch_from_blobs(&p, alien, NULL, NULL, NULL, &opts)); cl_assert(p != NULL); delta = git_patch_get_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_DELETED, delta->status); cl_assert((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); git_patch_free(p); cl_git_pass(git_patch_from_blobs(&p, NULL, NULL, alien, NULL, &opts)); cl_assert(p != NULL); delta = git_patch_get_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_ADDED, delta->status); cl_assert((delta->flags & GIT_DIFF_FLAG_BINARY) != 0); cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); git_patch_free(p); }