void test_diff_tree__0(void) { /* grabbed a couple of commit oids from the history of the attr repo */ const char *a_commit = "605812a"; const char *b_commit = "370fe9ec22"; const char *c_commit = "f5b0af1fb4f5c"; git_tree *c; g_repo = cl_git_sandbox_init("attr"); cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); cl_assert((c = resolve_commit_oid_to_tree(g_repo, c_commit)) != NULL); opts.context_lines = 1; opts.interhunk_lines = 1; cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); cl_git_pass(git_diff_foreach( diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect)); cl_assert_equal_i(5, expect.files); cl_assert_equal_i(2, expect.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(1, expect.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(2, expect.file_status[GIT_DELTA_MODIFIED]); cl_assert_equal_i(5, expect.hunks); cl_assert_equal_i(7 + 24 + 1 + 6 + 6, expect.lines); cl_assert_equal_i(1, expect.line_ctxt); cl_assert_equal_i(24 + 1 + 5 + 5, expect.line_adds); cl_assert_equal_i(7 + 1, expect.line_dels); git_diff_free(diff); diff = NULL; memset(&expect, 0, sizeof(expect)); cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, c, b, &opts)); cl_git_pass(git_diff_foreach( diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect)); cl_assert_equal_i(2, expect.files); cl_assert_equal_i(0, expect.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(0, expect.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(2, expect.file_status[GIT_DELTA_MODIFIED]); cl_assert_equal_i(2, expect.hunks); cl_assert_equal_i(8 + 15, expect.lines); cl_assert_equal_i(1, expect.line_ctxt); cl_assert_equal_i(1, expect.line_adds); cl_assert_equal_i(7 + 14, expect.line_dels); git_tree_free(c); }
PyObject * Tree_diff(Tree *self, PyObject *args, PyObject *kwds) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_diff_list *diff; git_tree* tree = NULL; git_index* index; git_repository *repo; int err, empty_tree = 0; char *keywords[] = {"obj", "flags", "empty_tree", NULL}; Diff *py_diff; PyObject *py_obj = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oii", keywords, &py_obj, &opts.flags, &empty_tree)) return NULL; repo = git_tree_owner(self->tree); if (py_obj == NULL) { if (empty_tree > 0) err = git_diff_tree_to_tree(&diff, repo, self->tree, NULL, &opts); else err = git_diff_tree_to_workdir(&diff, repo, self->tree, &opts); } else if (PyObject_TypeCheck(py_obj, &TreeType)) { tree = ((Tree *)py_obj)->tree; err = git_diff_tree_to_tree(&diff, repo, self->tree, tree, &opts); } else if (PyObject_TypeCheck(py_obj, &IndexType)) { index = ((Index *)py_obj)->index; err = git_diff_tree_to_index(&diff, repo, self->tree, index, &opts); } 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(self->repo); py_diff->repo = self->repo; py_diff->list = diff; } return (PyObject*)py_diff; }
void test_diff_tree__larger_hunks(void) { const char *a_commit = "d70d245ed97ed2aa596dd1af6536e4bfdb047b69"; const char *b_commit = "7a9e0b02e63179929fed24f0a3e0f19168114d10"; git_tree *a, *b; git_diff_options opts = {0}; git_diff_list *diff = NULL; size_t d, num_d, h, num_h, l, num_l, header_len, line_len; const git_diff_delta *delta; git_diff_patch *patch; const git_diff_range *range; const char *header, *line; char origin; g_repo = cl_git_sandbox_init("diff"); cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); opts.context_lines = 1; opts.interhunk_lines = 0; cl_git_pass(git_diff_tree_to_tree(g_repo, &opts, a, b, &diff)); num_d = git_diff_num_deltas(diff); for (d = 0; d < num_d; ++d) { cl_git_pass(git_diff_get_patch(&patch, &delta, diff, d)); cl_assert(patch && delta); num_h = git_diff_patch_num_hunks(patch); for (h = 0; h < num_h; h++) { cl_git_pass(git_diff_patch_get_hunk( &range, &header, &header_len, &num_l, patch, h)); for (l = 0; l < num_l; ++l) { cl_git_pass(git_diff_patch_get_line_in_hunk( &origin, &line, &line_len, NULL, NULL, patch, h, l)); cl_assert(line); } cl_git_fail(git_diff_patch_get_line_in_hunk( &origin, &line, &line_len, NULL, NULL, patch, h, num_l)); } cl_git_fail(git_diff_patch_get_hunk( &range, &header, &header_len, &num_l, patch, num_h)); git_diff_patch_free(patch); } cl_git_fail(git_diff_get_patch(&patch, &delta, diff, num_d)); cl_assert_equal_i(2, (int)num_d); git_diff_list_free(diff); diff = NULL; git_tree_free(a); git_tree_free(b); }
PyObject * Tree_diff_to_tree(Tree *self, PyObject *args, PyObject *kwds) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_diff *diff; git_tree *from, *to, *tmp; Repository *py_repo; int err, swap = 0; char *keywords[] = {"obj", "flags", "context_lines", "interhunk_lines", "swap", NULL}; Tree *py_tree = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!IHHi", keywords, &TreeType, &py_tree, &opts.flags, &opts.context_lines, &opts.interhunk_lines, &swap)) return NULL; py_repo = self->repo; to = (py_tree == NULL) ? NULL : py_tree->tree; from = self->tree; if (swap > 0) { tmp = from; from = to; to = tmp; } err = git_diff_tree_to_tree(&diff, py_repo->repo, from, to, &opts); if (err < 0) return Error_set(err); return wrap_diff(diff, py_repo); }
void test_diff_binary__empty_for_no_diff(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_oid id; git_commit *commit; git_tree *tree; git_diff *diff; git_buf actual = GIT_BUF_INIT; opts.flags = GIT_DIFF_SHOW_BINARY | GIT_DIFF_FORCE_BINARY; opts.id_abbrev = GIT_OID_HEXSZ; repo = cl_git_sandbox_init("renames"); cl_git_pass(git_oid_fromstr(&id, "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13")); cl_git_pass(git_commit_lookup(&commit, repo, &id)); cl_git_pass(git_commit_tree(&tree, commit)); cl_git_pass(git_diff_tree_to_tree(&diff, repo, tree, tree, &opts)); cl_git_pass(git_diff_print(diff, GIT_DIFF_FORMAT_PATCH, git_diff_print_callback__to_buf, &actual)); cl_assert_equal_s("", actual.ptr); git_buf_dispose(&actual); git_diff_free(diff); git_commit_free(commit); git_tree_free(tree); }
std::vector<std::string> Commit::getAffectedFiles() const { git_tree* tree = nullptr; git_tree* tree2 = nullptr; int error = git_commit_tree(&tree, get()); throw_on_error(error); try { error = git_commit_tree(&tree2, parent(0).get()); } catch (GitException e) { tree2 = nullptr; // probably initial commit } git_diff* diff = nullptr; git_diff_tree_to_tree(&diff, getRepo(), tree2, tree, 0); std::vector<std::string> ret; git_diff_foreach(diff, [](const git_diff_delta* entry, float progress, void* payload) { std::string str = entry->old_file.path; ((std::vector<std::string>*)payload)->push_back(str); return 0; }, nullptr, nullptr, &ret); git_tree_free(tree); git_tree_free(tree2); git_diff_free(diff); return ret; }
void test_diff_tree__bare(void) { const char *a_commit = "8496071c1b46c85"; const char *b_commit = "be3563ae3f79"; g_repo = cl_git_sandbox_init("testrepo.git"); cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); opts.context_lines = 1; opts.interhunk_lines = 1; cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); cl_git_pass(git_diff_foreach( diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect)); cl_assert_equal_i(3, expect.files); cl_assert_equal_i(2, expect.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(0, expect.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(1, expect.file_status[GIT_DELTA_MODIFIED]); cl_assert_equal_i(3, expect.hunks); cl_assert_equal_i(4, expect.lines); cl_assert_equal_i(0, expect.line_ctxt); cl_assert_equal_i(3, expect.line_adds); cl_assert_equal_i(1, expect.line_dels); }
Diff diff(Repository const & repo, Tree & a, Tree & b, git_diff_options const & opts) { git_diff * diff; auto op_res = git_diff_tree_to_tree(&diff, repo.ptr(), a.ptr(), b.ptr(), &opts); assert(op_res == 0); return Diff(diff); }
void test_diff_tree__merge(void) { /* grabbed a couple of commit oids from the history of the attr repo */ const char *a_commit = "605812a"; const char *b_commit = "370fe9ec22"; const char *c_commit = "f5b0af1fb4f5c"; git_tree *a, *b, *c; git_diff_list *diff1 = NULL, *diff2 = NULL; diff_expects exp; g_repo = cl_git_sandbox_init("attr"); cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); cl_assert((c = resolve_commit_oid_to_tree(g_repo, c_commit)) != NULL); cl_git_pass(git_diff_tree_to_tree(g_repo, NULL, a, b, &diff1)); cl_git_pass(git_diff_tree_to_tree(g_repo, NULL, c, b, &diff2)); git_tree_free(a); git_tree_free(b); git_tree_free(c); cl_git_pass(git_diff_merge(diff1, diff2)); git_diff_list_free(diff2); memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_foreach( diff1, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn)); cl_assert_equal_i(6, exp.files); cl_assert_equal_i(2, exp.file_adds); cl_assert_equal_i(1, exp.file_dels); cl_assert_equal_i(3, exp.file_mods); cl_assert_equal_i(6, exp.hunks); cl_assert_equal_i(59, exp.lines); cl_assert_equal_i(1, exp.line_ctxt); cl_assert_equal_i(36, exp.line_adds); cl_assert_equal_i(22, exp.line_dels); git_diff_list_free(diff1); }
void test_diff_tree__merge(void) { /* grabbed a couple of commit oids from the history of the attr repo */ const char *a_commit = "605812a"; const char *b_commit = "370fe9ec22"; const char *c_commit = "f5b0af1fb4f5c"; git_tree *c; git_diff *diff1 = NULL, *diff2 = NULL; g_repo = cl_git_sandbox_init("attr"); cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); cl_assert((c = resolve_commit_oid_to_tree(g_repo, c_commit)) != NULL); cl_git_pass(git_diff_tree_to_tree(&diff1, g_repo, a, b, NULL)); cl_git_pass(git_diff_tree_to_tree(&diff2, g_repo, c, b, NULL)); git_tree_free(c); cl_git_pass(git_diff_merge(diff1, diff2)); git_diff_free(diff2); cl_git_pass(git_diff_foreach( diff1, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect)); cl_assert_equal_i(6, expect.files); cl_assert_equal_i(2, expect.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(1, expect.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(3, expect.file_status[GIT_DELTA_MODIFIED]); cl_assert_equal_i(6, expect.hunks); cl_assert_equal_i(59, expect.lines); cl_assert_equal_i(1, expect.line_ctxt); cl_assert_equal_i(36, expect.line_adds); cl_assert_equal_i(22, expect.line_dels); git_diff_free(diff1); }
void test_diff_tree__checks_options_version(void) { const char *a_commit = "8496071c1b46c85"; const char *b_commit = "be3563ae3f79"; const git_error *err; g_repo = cl_git_sandbox_init("testrepo.git"); cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); opts.version = 0; cl_git_fail(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); err = giterr_last(); cl_assert_equal_i(GITERR_INVALID, err->klass); giterr_clear(); opts.version = 1024; cl_git_fail(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); err = giterr_last(); }
void process_tree_to_tree_diffing( const char *old_commit, const char *new_commit) { g_repo = cl_git_sandbox_init("unsymlinked.git"); cl_assert((a = resolve_commit_oid_to_tree(g_repo, old_commit)) != NULL); cl_assert((b = resolve_commit_oid_to_tree(g_repo, new_commit)) != NULL); cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); cl_git_pass(git_diff_foreach( diff, diff_file_cb, NULL, NULL, NULL, &expect)); }
PyObject * Tree_diff(Tree *self, PyObject *args) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_diff_list *diff; int err; Diff *py_diff; PyObject *py_obj = NULL; if (!PyArg_ParseTuple(args, "|Oi", &py_obj, &opts.flags)) return NULL; if (py_obj == NULL) { err = git_diff_tree_to_workdir( &diff, self->repo->repo, self->tree, &opts); } else if (PyObject_TypeCheck(py_obj, &TreeType)) { err = git_diff_tree_to_tree( &diff, self->repo->repo, self->tree, ((Tree *)py_obj)->tree, &opts); } else if (PyObject_TypeCheck(py_obj, &IndexType)) { err = git_diff_tree_to_index( &diff, self->repo->repo, self->tree, ((Index *)py_obj)->index, &opts); } 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(self->repo); py_diff->repo = self->repo; py_diff->list = diff; } return (PyObject*)py_diff; }
void test_patch( const char *one, const char *two, const git_diff_options *opts, const char *expected) { git_oid id_one, id_two; git_index *index = NULL; git_commit *commit_one, *commit_two = NULL; git_tree *tree_one, *tree_two; git_diff *diff; git_patch *patch; git_buf actual = GIT_BUF_INIT; cl_git_pass(git_oid_fromstr(&id_one, one)); cl_git_pass(git_commit_lookup(&commit_one, repo, &id_one)); cl_git_pass(git_commit_tree(&tree_one, commit_one)); if (two) { cl_git_pass(git_oid_fromstr(&id_two, two)); cl_git_pass(git_commit_lookup(&commit_two, repo, &id_two)); cl_git_pass(git_commit_tree(&tree_two, commit_two)); } else { cl_git_pass(git_repository_index(&index, repo)); cl_git_pass(git_index_write_tree(&id_two, index)); cl_git_pass(git_tree_lookup(&tree_two, repo, &id_two)); } cl_git_pass(git_diff_tree_to_tree(&diff, repo, tree_one, tree_two, opts)); cl_git_pass(git_patch_from_diff(&patch, diff, 0)); cl_git_pass(git_patch_to_buf(&actual, patch)); cl_assert_equal_s(expected, actual.ptr); git_buf_clear(&actual); cl_git_pass(git_diff_print(diff, GIT_DIFF_FORMAT_PATCH, git_diff_print_callback__to_buf, &actual)); cl_assert_equal_s(expected, actual.ptr); git_buf_dispose(&actual); git_patch_free(patch); git_diff_free(diff); git_tree_free(tree_one); git_tree_free(tree_two); git_commit_free(commit_one); git_commit_free(commit_two); git_index_free(index); }
Diff::Diff(const Commit& comm, const Commit& comm2) { git_tree *commit_tree = nullptr, *parent_tree = nullptr; int error = 0; error = git_commit_tree(&commit_tree, comm.get()); throw_on_error(error); error = git_commit_tree(&parent_tree, comm2.get()); throw_on_error(error); git_diff *d = nullptr; error = git_diff_tree_to_tree( &d, comm.getRepo(), commit_tree, parent_tree, nullptr); throw_on_error(error); // TODO: Make this exception safe git_tree_free(commit_tree); git_tree_free(parent_tree); diff = std::shared_ptr<git_diff>(d, git_diff_free); }
void test_diff_tree__larger_hunks(void) { const char *a_commit = "d70d245ed97ed2aa596dd1af6536e4bfdb047b69"; const char *b_commit = "7a9e0b02e63179929fed24f0a3e0f19168114d10"; size_t d, num_d, h, num_h, l, num_l; git_patch *patch; const git_diff_hunk *hunk; const git_diff_line *line; g_repo = cl_git_sandbox_init("diff"); cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); opts.context_lines = 1; opts.interhunk_lines = 0; cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); num_d = git_diff_num_deltas(diff); for (d = 0; d < num_d; ++d) { cl_git_pass(git_patch_from_diff(&patch, diff, d)); cl_assert(patch); num_h = git_patch_num_hunks(patch); for (h = 0; h < num_h; h++) { cl_git_pass(git_patch_get_hunk(&hunk, &num_l, patch, h)); for (l = 0; l < num_l; ++l) { cl_git_pass(git_patch_get_line_in_hunk(&line, patch, h, l)); cl_assert(line); } cl_git_fail(git_patch_get_line_in_hunk(&line, patch, h, num_l)); } cl_git_fail(git_patch_get_hunk(&hunk, &num_l, patch, num_h)); git_patch_free(patch); } cl_git_fail(git_patch_from_diff(&patch, diff, num_d)); cl_assert_equal_i(2, (int)num_d); }
void test_diff_parse__get_patch_from_diff(void) { git_repository *repo; git_diff *computed, *parsed; git_tree *a, *b; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_buf computed_buf = GIT_BUF_INIT; git_patch *patch_computed, *patch_parsed; repo = cl_git_sandbox_init("diff"); opts.flags = GIT_DIFF_SHOW_BINARY; cl_assert((a = resolve_commit_oid_to_tree(repo, "d70d245ed97ed2aa596dd1af6536e4bfdb047b69")) != NULL); cl_assert((b = resolve_commit_oid_to_tree(repo, "7a9e0b02e63179929fed24f0a3e0f19168114d10")) != NULL); cl_git_pass(git_diff_tree_to_tree(&computed, repo, a, b, &opts)); cl_git_pass(git_diff_to_buf(&computed_buf, computed, GIT_DIFF_FORMAT_PATCH)); cl_git_pass(git_patch_from_diff(&patch_computed, computed, 0)); cl_git_pass(git_diff_from_buffer(&parsed, computed_buf.ptr, computed_buf.size)); cl_git_pass(git_patch_from_diff(&patch_parsed, parsed, 0)); cl_assert_equal_i( git_patch_num_hunks(patch_computed), git_patch_num_hunks(patch_parsed)); git_patch_free(patch_computed); git_patch_free(patch_parsed); git_tree_free(a); git_tree_free(b); git_diff_free(computed); git_diff_free(parsed); git_buf_free(&computed_buf); cl_git_sandbox_cleanup(); }
static void test_tree_to_tree_computed_to_parsed( const char *sandbox, const char *a_id, const char *b_id, uint32_t diff_flags, uint32_t find_flags) { git_repository *repo; git_diff *computed, *parsed; git_tree *a, *b; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; git_buf computed_buf = GIT_BUF_INIT; repo = cl_git_sandbox_init(sandbox); opts.id_abbrev = GIT_OID_HEXSZ; opts.flags = GIT_DIFF_SHOW_BINARY | diff_flags; findopts.flags = find_flags; cl_assert((a = resolve_commit_oid_to_tree(repo, a_id)) != NULL); cl_assert((b = resolve_commit_oid_to_tree(repo, b_id)) != NULL); cl_git_pass(git_diff_tree_to_tree(&computed, repo, a, b, &opts)); if (find_flags) cl_git_pass(git_diff_find_similar(computed, &findopts)); cl_git_pass(git_diff_to_buf(&computed_buf, computed, GIT_DIFF_FORMAT_PATCH)); cl_git_pass(git_diff_from_buffer(&parsed, computed_buf.ptr, computed_buf.size)); diff_assert_equal(computed, parsed); git_tree_free(a); git_tree_free(b); git_diff_free(computed); git_diff_free(parsed); git_buf_free(&computed_buf); cl_git_sandbox_cleanup(); }
void test_diff_tree__bare(void) { const char *a_commit = "8496071c1b46c85"; const char *b_commit = "be3563ae3f79"; git_tree *a, *b; git_diff_options opts = {0}; git_diff_list *diff = NULL; diff_expects exp; g_repo = cl_git_sandbox_init("testrepo.git"); cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); opts.context_lines = 1; opts.interhunk_lines = 1; memset(&exp, 0, sizeof(exp)); cl_git_pass(git_diff_tree_to_tree(g_repo, &opts, a, b, &diff)); cl_git_pass(git_diff_foreach( diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn)); cl_assert(exp.files == 3); cl_assert(exp.file_adds == 2); cl_assert(exp.file_dels == 0); cl_assert(exp.file_mods == 1); cl_assert(exp.hunks == 3); cl_assert(exp.lines == 4); cl_assert(exp.line_ctxt == 0); cl_assert(exp.line_adds == 3); cl_assert(exp.line_dels == 1); git_diff_list_free(diff); git_tree_free(a); git_tree_free(b); }
void test_apply_both__generated_diff(void) { git_oid a_oid, b_oid; git_commit *a_commit, *b_commit; git_tree *a_tree, *b_tree; git_diff *diff; git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT; struct merge_index_entry both_expected[] = { { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" }, { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" }, { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" }, { 0100644, "a7b066537e6be7109abfe4ff97b675d4e077da20", 0, "veal.txt" }, }; size_t both_expected_cnt = sizeof(both_expected) / sizeof(struct merge_index_entry); git_oid_fromstr(&a_oid, "539bd011c4822c560c1d17cab095006b7a10f707"); git_oid_fromstr(&b_oid, "7c7bf85e978f1d18c0566f702d2cb7766b9c8d4f"); cl_git_pass(git_commit_lookup(&a_commit, repo, &a_oid)); cl_git_pass(git_commit_lookup(&b_commit, repo, &b_oid)); cl_git_pass(git_commit_tree(&a_tree, a_commit)); cl_git_pass(git_commit_tree(&b_tree, b_commit)); cl_git_pass(git_diff_tree_to_tree(&diff, repo, a_tree, b_tree, &diff_opts)); cl_git_pass(git_apply(repo, diff, GIT_APPLY_LOCATION_BOTH, NULL)); validate_apply_index(repo, both_expected, both_expected_cnt); validate_apply_workdir(repo, both_expected, both_expected_cnt); git_diff_free(diff); git_tree_free(a_tree); git_tree_free(b_tree); git_commit_free(a_commit); git_commit_free(b_commit); }
void test_diff_tree__issue_1397(void) { /* this test shows that it is not needed */ g_repo = cl_git_sandbox_init("issue_1397"); cl_repo_set_bool(g_repo, "core.autocrlf", true); cl_assert((a = resolve_commit_oid_to_tree(g_repo, "8a7ef04")) != NULL); cl_assert((b = resolve_commit_oid_to_tree(g_repo, "7f483a7")) != NULL); cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); cl_git_pass(git_diff_foreach(diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect)); cl_assert_equal_i(1, expect.files); cl_assert_equal_i(0, expect.file_status[GIT_DELTA_DELETED]); cl_assert_equal_i(1, expect.file_status[GIT_DELTA_MODIFIED]); cl_assert_equal_i(0, expect.file_status[GIT_DELTA_ADDED]); cl_assert_equal_i(0, expect.file_status[GIT_DELTA_TYPECHANGE]); }
int luagi_diff_tree_to_tree( lua_State *L ) { git_repository **repo = checkrepo( L, 1 ); git_tree **old_tree = checktree_at( L, 2 ); git_tree **new_tree = checktree_at( L, 3 ); git_diff_options opts; luagi_diff_init_options( L, 4, &opts ); git_diff **diff = (git_diff **) lua_newuserdata( L, sizeof( git_diff *) ); if( git_diff_tree_to_tree( diff, *repo, *old_tree, *new_tree, &opts ) ) { const git_error *err = giterr_last(); lua_pushnil( L ); lua_pushstring( L, err->message ); return 2; } ltk_setmetatable( L, LUAGI_DIFF_FUNCS ); return 1; }
/* Helper to find how many files in a commit changed from its nth parent. */ static int match_with_parent(git_commit *commit, int i, git_diff_options *opts) { git_commit *parent; git_tree *a, *b; git_diff *diff; int ndeltas; check_lg2( git_commit_parent(&parent, commit, (size_t)i), "Get parent", NULL); check_lg2(git_commit_tree(&a, parent), "Tree for parent", NULL); check_lg2(git_commit_tree(&b, commit), "Tree for commit", NULL); check_lg2( git_diff_tree_to_tree(&diff, git_commit_owner(commit), a, b, opts), "Checking diff between parent and commit", NULL); ndeltas = (int)git_diff_num_deltas(diff); git_diff_free(diff); git_tree_free(a); git_tree_free(b); git_commit_free(parent); return ndeltas > 0; }
/* * call-seq: * Tree.diff(repo, tree, diffable[, options]) -> diff * * Returns a diff between the `tree` and the diffable object that was given. * +diffable+ can either be a +Rugged::Commit+, a +Rugged::Tree+, a +Rugged::Index+, * or +nil+. * * The +tree+ object will be used as the "old file" side of the diff, while the * parent tree or the +diffable+ object will be used for the "new file" side. * * If +tree+ or +diffable+ are nil, they will be treated as an empty tree. Passing * both as `nil` will raise an exception. * * The following options can be passed in the +options+ Hash: * * :paths :: * An array of paths / fnmatch patterns to constrain the diff to a specific * set of files. Also see +:disable_pathspec_match+. * * :max_size :: * An integer specifying the maximum byte size of a file before a it will * be treated as binary. The default value is 512MB. * * :context_lines :: * The number of unchanged lines that define the boundary of a hunk (and * to display before and after the actual changes). The default is 3. * * :interhunk_lines :: * The maximum number of unchanged lines between hunk boundaries before the hunks * will be merged into a one. The default is 0. * * :old_prefix :: * The virtual "directory" to prefix to old filenames in hunk headers. * The default is "a". * * :new_prefix :: * The virtual "directory" to prefix to new filenames in hunk headers. * The default is "b". * * :reverse :: * If true, the sides of the diff will be reversed. * * :force_text :: * If true, all files will be treated as text, disabling binary attributes & detection. * * :ignore_whitespace :: * If true, all whitespace will be ignored. * * :ignore_whitespace_change :: * If true, changes in amount of whitespace will be ignored. * * :ignore_whitespace_eol :: * If true, whitespace at end of line will be ignored. * * :ignore_submodules :: * if true, submodules will be excluded from the diff completely. * * :patience :: * If true, the "patience diff" algorithm will be used (currenlty unimplemented). * * :include_ignored :: * If true, ignored files will be included in the diff. * * :include_untracked :: * If true, untracked files will be included in the diff. * * :include_unmodified :: * If true, unmodified files will be included in the diff. * * :recurse_untracked_dirs :: * Even if +:include_untracked+ is true, untracked directories will only be * marked with a single entry in the diff. If this flag is set to true, * all files under ignored directories will be included in the diff, too. * * :disable_pathspec_match :: * If true, the given +:paths+ will be applied as exact matches, instead of * as fnmatch patterns. * * :deltas_are_icase :: * If true, filename comparisons will be made with case-insensitivity. * * :include_untracked_content :: * if true, untracked content will be contained in the the diff patch text. * * :skip_binary_check :: * If true, diff deltas will be generated without spending time on binary * detection. This is useful to improve performance in cases where the actual * file content difference is not needed. * * :include_typechange :: * If true, type changes for files will not be interpreted as deletion of * the "old file" and addition of the "new file", but will generate * typechange records. * * :include_typechange_trees :: * Even if +:include_typechange+ is true, blob -> tree changes will still * usually be handled as a deletion of the blob. If this flag is set to true, * blob -> tree changes will be marked as typechanges. * * :ignore_filemode :: * If true, file mode changes will be ignored. * * :recurse_ignored_dirs :: * Even if +:include_ignored+ is true, ignored directories will only be * marked with a single entry in the diff. If this flag is set to true, * all files under ignored directories will be included in the diff, too. * * Examples: * * # Emulating `git diff <treeish>` * tree = Rugged::Tree.lookup(repo, "d70d245ed97ed2aa596dd1af6536e4bfdb047b69") * diff = tree.diff(repo.index) * diff.merge!(tree.diff) * * # Tree-to-Tree Diff * tree = Rugged::Tree.lookup(repo, "d70d245ed97ed2aa596dd1af6536e4bfdb047b69") * other_tree = Rugged::Tree.lookup(repo, "7a9e0b02e63179929fed24f0a3e0f19168114d10") * diff = tree.diff(other_tree) */ static VALUE rb_git_tree_diff_(int argc, VALUE *argv, VALUE self) { git_tree *tree = NULL; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_repository *repo = NULL; git_diff *diff = NULL; VALUE rb_self, rb_repo, rb_other, rb_options; int error; rb_scan_args(argc, argv, "22", &rb_repo, &rb_self, &rb_other, &rb_options); rugged_parse_diff_options(&opts, rb_options); Data_Get_Struct(rb_repo, git_repository, repo); if (!NIL_P(rb_self)) { if (!rb_obj_is_kind_of(rb_self, rb_cRuggedTree)) rb_raise(rb_eTypeError, "At least a Rugged::Tree object is required for diffing"); Data_Get_Struct(rb_self, git_tree, tree); } if (NIL_P(rb_other)) { if (tree == NULL) { xfree(opts.pathspec.strings); rb_raise(rb_eTypeError, "Need 'old' or 'new' for diffing"); } error = git_diff_tree_to_tree(&diff, repo, tree, NULL, &opts); } else { if (TYPE(rb_other) == T_STRING) rb_other = rugged_object_rev_parse(rb_repo, rb_other, 1); if (rb_obj_is_kind_of(rb_other, rb_cRuggedCommit)) { git_tree *other_tree; git_commit *commit; Data_Get_Struct(rb_other, git_commit, commit); error = git_commit_tree(&other_tree, commit); if (!error) { error = git_diff_tree_to_tree(&diff, repo, tree, other_tree, &opts); git_tree_free(other_tree); } } else if (rb_obj_is_kind_of(rb_other, rb_cRuggedTree)) { git_tree *other_tree; Data_Get_Struct(rb_other, git_tree, other_tree); error = git_diff_tree_to_tree(&diff, repo, tree, other_tree, &opts); } else if (rb_obj_is_kind_of(rb_other, rb_cRuggedIndex)) { git_index *index; Data_Get_Struct(rb_other, git_index, index); error = git_diff_tree_to_index(&diff, repo, tree, index, &opts); } else { xfree(opts.pathspec.strings); rb_raise(rb_eTypeError, "A Rugged::Commit, Rugged::Tree or Rugged::Index instance is required"); } } xfree(opts.pathspec.strings); rugged_exception_check(error); return rugged_diff_new(rb_cRuggedDiff, rb_repo, diff); }
void QGit::commitDiffContent(QString first, QString second, QList<QString> files) { git_commit *first_commit = nullptr, *second_commit = nullptr; git_object *first_obj = nullptr, *second_obj = nullptr; git_tree *first_tree = nullptr, *second_tree = nullptr; const git_diff_delta *delta = nullptr; git_repository *repo = nullptr; git_patch *patch = nullptr; QList<QGitDiffFile> items; git_diff *diff = nullptr; QGitError error; int res = 0; try { res = git_repository_open(&repo, m_path.absolutePath().toUtf8().constData()); if (res) { throw QGitError("git_repository_open", res); } if (!first.isEmpty()) { res = git_revparse_single(&first_obj, repo, first.toLatin1()); if (res) { throw QGitError("git_revparse_single(first)", res); } res = git_commit_lookup(&first_commit, repo, git_object_id(first_obj)); if (res) { throw QGitError("git_commit_lookup(first)", res); } res = git_commit_tree(&first_tree, first_commit); if (res) { throw QGitError("git_commit_tree(first)", res); } } if (second == "staged") { git_diff_options options; res = git_revparse_single(&first_obj, repo, "HEAD^{tree}"); if (res) { throw QGitError("git_revparse_single(staged)", res); } res = git_tree_lookup(&first_tree, repo, git_object_id(first_obj)); if (res) { throw QGitError("git_tree_lookup(staged)", res); } memset(&options, 0, sizeof(options)); options.version = GIT_DIFF_OPTIONS_VERSION; options.flags = GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_SHOW_UNTRACKED_CONTENT; options.context_lines = 3; res = git_diff_tree_to_index(&diff, repo, first_tree, nullptr, &options); if (res) { throw QGitError("git_diff_tree_to_index(staged)", res); } } else if (second == "unstaged") { git_diff_options options; memset(&options, 0, sizeof(options)); options.version = GIT_DIFF_OPTIONS_VERSION; options.flags = GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_SHOW_UNTRACKED_CONTENT; options.context_lines = 3; res = git_diff_index_to_workdir(&diff, repo, nullptr, &options); if (res) { throw QGitError("git_diff_index_to_workdir", res); } } else { res = git_revparse_single(&second_obj, repo, second.toLatin1()); if (res) { throw QGitError("git_revparse_single(second)", res); } res = git_commit_lookup(&second_commit, repo, git_object_id(second_obj)); if (res) { throw QGitError("git_commit_lookup(second)", res); } res = git_commit_tree(&second_tree, second_commit); if (res) { throw QGitError("git_commit_tree(second)", res); } res = git_diff_tree_to_tree(&diff, repo, first_tree, second_tree, nullptr); if (res) { throw QGitError("git_diff_tree_to_tree", res); } } size_t _count = git_diff_num_deltas(diff); for(size_t c = 0; c < _count; c++) { delta = git_diff_get_delta(diff, c); QGitDiffFile item(delta); if (files.contains(item.new_file().path())) { res = git_patch_from_diff(&patch, diff, c); if (res) { throw QGitError("git_patch_from_diff", res); } size_t hunks = git_patch_num_hunks(patch); for(size_t hunk_cnt = 0; hunk_cnt < hunks; hunk_cnt++) { const git_diff_hunk *hunk = nullptr; res = git_patch_get_hunk(&hunk, nullptr, patch, hunk_cnt); if (res) { throw QGitError("git_patch_get_hunk", res); } QGitDiffHunk hunkObj(hunk); const git_diff_line *line = nullptr; int lines = git_patch_num_lines_in_hunk(patch, hunk_cnt); if (lines > 0) { for(int line_cnt = 0; line_cnt < lines; line_cnt++) { res = git_patch_get_line_in_hunk(&line, patch, hunk_cnt, static_cast<size_t>(line_cnt)); if (res) { throw QGitError("git_patch_get_line_in_hunk", res); } hunkObj.addLine(line); } } item.addHunk(hunkObj); } items.append(item); } } } catch(const QGitError &ex) { error = ex; } emit commitDiffContentReply(first, second, items, error); }
static git_blame__origin* find_origin( git_blame *blame, git_commit *parent, git_blame__origin *origin) { git_blame__origin *porigin = NULL; git_diff *difflist = NULL; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_tree *otree=NULL, *ptree=NULL; /* Get the trees from this commit and its parent */ if (0 != git_commit_tree(&otree, origin->commit) || 0 != git_commit_tree(&ptree, parent)) goto cleanup; /* Configure the diff */ diffopts.context_lines = 0; diffopts.flags = GIT_DIFF_SKIP_BINARY_CHECK; /* Check to see if files we're interested have changed */ diffopts.pathspec.count = blame->paths.length; diffopts.pathspec.strings = (char**)blame->paths.contents; if (0 != git_diff_tree_to_tree(&difflist, blame->repository, ptree, otree, &diffopts)) goto cleanup; if (!git_diff_num_deltas(difflist)) { /* No changes; copy data */ git_blame__get_origin(&porigin, blame, parent, origin->path); } else { git_diff_find_options findopts = GIT_DIFF_FIND_OPTIONS_INIT; int i; /* Generate a full diff between the two trees */ git_diff_free(difflist); diffopts.pathspec.count = 0; if (0 != git_diff_tree_to_tree(&difflist, blame->repository, ptree, otree, &diffopts)) goto cleanup; /* Let diff find renames */ findopts.flags = GIT_DIFF_FIND_RENAMES; if (0 != git_diff_find_similar(difflist, &findopts)) goto cleanup; /* Find one that matches */ for (i=0; i<(int)git_diff_num_deltas(difflist); i++) { const git_diff_delta *delta = git_diff_get_delta(difflist, i); if (!git_vector_bsearch(NULL, &blame->paths, delta->new_file.path)) { git_vector_insert_sorted(&blame->paths, (void*)git__strdup(delta->old_file.path), paths_on_dup); make_origin(&porigin, parent, delta->old_file.path); } } } cleanup: git_diff_free(difflist); git_tree_free(otree); git_tree_free(ptree); return porigin; }
void QGit::commitDiff(QString commitId) { const git_diff_delta *delta = nullptr; git_tree *commit_tree = nullptr; git_tree *parent_tree = nullptr; git_repository *repo = nullptr; git_commit *parent = nullptr; git_commit *commit = nullptr; git_object *obj = nullptr; git_diff *diff = nullptr; QList<QGitCommitDiffParent> parents; QGitSignature commitAuthor, commitCommiter; QDateTime commitTime; QString commitMessage; QGitCommit commitDiff; unsigned int parentCount; int res = 0; QGitError error; try { res = git_repository_open(&repo, m_path.absolutePath().toUtf8().constData()); if (res) { throw QGitError("git_repository_open", res); } if (commitId.isEmpty()) { commitId = QStringLiteral("HEAD"); } res = git_revparse_single(&obj, repo, commitId.toLatin1()); if (res) { throw QGitError("git_revparse_single", res); } res = git_commit_lookup(&commit, repo, git_object_id(obj)); if (res) { throw QGitError("git_commit_lookup", res); } res = git_commit_tree(&commit_tree, commit); if (res) { throw QGitError("git_commit_tree", res); } commitAuthor = QGitSignature(QString::fromUtf8(git_commit_author(commit)->name), QString::fromUtf8(git_commit_author(commit)->email), QDateTime::fromMSecsSinceEpoch(git_commit_author(commit)->when.time * 1000)); commitCommiter = QGitSignature(QString::fromUtf8(git_commit_committer(commit)->name), QString::fromUtf8(git_commit_committer(commit)->email), QDateTime::fromMSecsSinceEpoch(git_commit_committer(commit)->when.time * 1000)); auto time = git_commit_time(commit); auto timeOffset = git_commit_time_offset(commit); commitTime = QDateTime::fromMSecsSinceEpoch(time * 1000); commitTime.setOffsetFromUtc(timeOffset * 60); commitMessage = QString::fromUtf8(git_commit_message(commit)); parentCount = git_commit_parentcount(commit); if (parentCount == 0) { QGitCommitDiffParent item; res = git_diff_tree_to_tree(&diff, repo, nullptr, commit_tree, nullptr); if (res) { throw QGitError("git_diff_tree_to_tree", res); } size_t _count = git_diff_num_deltas(diff); for(size_t c = 0; c < _count; c++) { delta = git_diff_get_delta(diff, c); item.addFile(delta); } git_diff_free(diff); diff = nullptr; parents.append(item); } else { for(unsigned int c = 0; c < parentCount; c++) { res = git_commit_parent(&parent, commit, c); if (res) { throw QGitError("git_commit_parent", res); } char commit_id[41] = {0, }; const git_oid *oid = git_commit_id(parent); git_oid_tostr(commit_id, 41, oid); QGitCommitDiffParent item(commit_id); res = git_commit_tree(&parent_tree, parent); if (res) { throw QGitError("git_commit_tree", res); } res = git_diff_tree_to_tree(&diff, repo, parent_tree, commit_tree, nullptr); if (res) { throw QGitError("git_diff_tree_to_tree", res); } size_t _count = git_diff_num_deltas(diff); for(size_t c = 0; c < _count; c++) { delta = git_diff_get_delta(diff, c); item.addFile(delta); } git_diff_free(diff); diff = nullptr; git_tree_free(parent_tree); parent_tree = nullptr; git_commit_free(parent); parent = nullptr; parents.append(item); } } } catch(const QGitError &ex) { error = ex; } commitDiff = QGitCommit(commitId, parents, commitTime, commitAuthor, commitCommiter, commitMessage); emit commitDiffReply(commitId, commitDiff, error); if (diff) { git_diff_free(diff); diff = nullptr; } if (parent_tree) { git_tree_free(parent_tree); parent_tree = nullptr; } if (parent) { git_commit_free(parent); parent = nullptr; } if (commit_tree) { git_tree_free(commit_tree); commit_tree = nullptr; } if(commit) { git_commit_free(commit); commit = nullptr; } if(obj) { git_object_free(obj); obj = nullptr; } if (repo) { git_repository_free(repo); repo = nullptr; } }
void test_diff_tree__diff_configs(void) { const char *a_commit = "d70d245e"; const char *b_commit = "7a9e0b02"; g_repo = cl_git_sandbox_init("diff"); cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, NULL)); cl_git_pass(git_diff_foreach(diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect)); cl_assert_equal_i(2, expect.files); cl_assert_equal_i(2, expect.file_status[GIT_DELTA_MODIFIED]); cl_assert_equal_i(6, expect.hunks); cl_assert_equal_i(55, expect.lines); cl_assert_equal_i(33, expect.line_ctxt); cl_assert_equal_i(7, expect.line_adds); cl_assert_equal_i(15, expect.line_dels); git_diff_free(diff); diff = NULL; set_config_int(g_repo, "diff.context", 1); memset(&expect, 0, sizeof(expect)); cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, NULL)); cl_git_pass(git_diff_foreach(diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect)); cl_assert_equal_i(2, expect.files); cl_assert_equal_i(2, expect.file_status[GIT_DELTA_MODIFIED]); cl_assert_equal_i(7, expect.hunks); cl_assert_equal_i(34, expect.lines); cl_assert_equal_i(12, expect.line_ctxt); cl_assert_equal_i(7, expect.line_adds); cl_assert_equal_i(15, expect.line_dels); git_diff_free(diff); diff = NULL; set_config_int(g_repo, "diff.context", 0); set_config_int(g_repo, "diff.noprefix", 1); memset(&expect, 0, sizeof(expect)); cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, NULL)); cl_git_pass(git_diff_foreach(diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect)); cl_assert_equal_i(2, expect.files); cl_assert_equal_i(2, expect.file_status[GIT_DELTA_MODIFIED]); cl_assert_equal_i(7, expect.hunks); cl_assert_equal_i(22, expect.lines); cl_assert_equal_i(0, expect.line_ctxt); cl_assert_equal_i(7, expect.line_adds); cl_assert_equal_i(15, expect.line_dels); }
int lg2_diff(git_repository *repo, int argc, char *argv[]) { git_tree *t1 = NULL, *t2 = NULL; git_diff *diff; struct opts o = { GIT_DIFF_OPTIONS_INIT, GIT_DIFF_FIND_OPTIONS_INIT, -1, 0, 0, GIT_DIFF_FORMAT_PATCH, NULL, NULL, "." }; parse_opts(&o, argc, argv); /** * Possible argument patterns: * * * <sha1> <sha2> * * <sha1> --cached * * <sha1> * * --cached * * --nocache (don't use index data in diff at all) * * nothing * * Currently ranged arguments like <sha1>..<sha2> and <sha1>...<sha2> * are not supported in this example */ if (o.treeish1) treeish_to_tree(&t1, repo, o.treeish1); if (o.treeish2) treeish_to_tree(&t2, repo, o.treeish2); if (t1 && t2) check_lg2( git_diff_tree_to_tree(&diff, repo, t1, t2, &o.diffopts), "diff trees", NULL); else if (o.cache != CACHE_NORMAL) { if (!t1) treeish_to_tree(&t1, repo, "HEAD"); if (o.cache == CACHE_NONE) check_lg2( git_diff_tree_to_workdir(&diff, repo, t1, &o.diffopts), "diff tree to working directory", NULL); else check_lg2( git_diff_tree_to_index(&diff, repo, t1, NULL, &o.diffopts), "diff tree to index", NULL); } else if (t1) check_lg2( git_diff_tree_to_workdir_with_index(&diff, repo, t1, &o.diffopts), "diff tree to working directory", NULL); else check_lg2( git_diff_index_to_workdir(&diff, repo, NULL, &o.diffopts), "diff index to working directory", NULL); /** Apply rename and copy detection if requested. */ if ((o.findopts.flags & GIT_DIFF_FIND_ALL) != 0) check_lg2( git_diff_find_similar(diff, &o.findopts), "finding renames and copies", NULL); /** Generate simple output using libgit2 display helper. */ if (!o.output) o.output = OUTPUT_DIFF; if (o.output != OUTPUT_DIFF) diff_print_stats(diff, &o); if ((o.output & OUTPUT_DIFF) != 0) { if (o.color >= 0) fputs(colors[0], stdout); check_lg2( git_diff_print(diff, o.format, color_printer, &o.color), "displaying diff", NULL); if (o.color >= 0) fputs(colors[0], stdout); } /** Cleanup before exiting. */ git_diff_free(diff); git_tree_free(t1); git_tree_free(t2); return 0; }
void test_diff_tree__options(void) { /* grabbed a couple of commit oids from the history of the attr repo */ const char *a_commit = "6bab5c79cd5140d0"; const char *b_commit = "605812ab7fe421fdd"; const char *c_commit = "f5b0af1fb4f5"; const char *d_commit = "a97cc019851"; git_tree *c, *d; diff_expects actual; int test_ab_or_cd[] = { 0, 0, 0, 0, 1, 1, 1, 1, 1 }; git_diff_options test_options[] = { /* a vs b tests */ DIFF_OPTS(GIT_DIFF_NORMAL, 1), DIFF_OPTS(GIT_DIFF_NORMAL, 3), DIFF_OPTS(GIT_DIFF_REVERSE, 2), DIFF_OPTS(GIT_DIFF_FORCE_TEXT, 2), /* c vs d tests */ DIFF_OPTS(GIT_DIFF_NORMAL, 3), DIFF_OPTS(GIT_DIFF_IGNORE_WHITESPACE, 3), DIFF_OPTS(GIT_DIFF_IGNORE_WHITESPACE_CHANGE, 3), DIFF_OPTS(GIT_DIFF_IGNORE_WHITESPACE_EOL, 3), DIFF_OPTS(GIT_DIFF_IGNORE_WHITESPACE | GIT_DIFF_REVERSE, 1), }; /* to generate these values: * - cd to tests/resources/attr, * - mv .gitted .git * - git diff [options] 6bab5c79cd5140d0 605812ab7fe421fdd * - mv .git .gitted */ #define EXPECT_STATUS_ADM(ADDS,DELS,MODS) { 0, ADDS, DELS, MODS, 0, 0, 0, 0, 0 } diff_expects test_expects[] = { /* a vs b tests */ { 5, 0, EXPECT_STATUS_ADM(3, 0, 2), 4, 0, 0, 51, 2, 46, 3 }, { 5, 0, EXPECT_STATUS_ADM(3, 0, 2), 4, 0, 0, 53, 4, 46, 3 }, { 5, 0, EXPECT_STATUS_ADM(0, 3, 2), 4, 0, 0, 52, 3, 3, 46 }, { 5, 0, EXPECT_STATUS_ADM(3, 0, 2), 5, 0, 0, 54, 3, 47, 4 }, /* c vs d tests */ { 1, 0, EXPECT_STATUS_ADM(0, 0, 1), 1, 0, 0, 22, 9, 10, 3 }, { 1, 0, EXPECT_STATUS_ADM(0, 0, 1), 1, 0, 0, 19, 12, 7, 0 }, { 1, 0, EXPECT_STATUS_ADM(0, 0, 1), 1, 0, 0, 20, 11, 8, 1 }, { 1, 0, EXPECT_STATUS_ADM(0, 0, 1), 1, 0, 0, 20, 11, 8, 1 }, { 1, 0, EXPECT_STATUS_ADM(0, 0, 1), 1, 0, 0, 18, 11, 0, 7 }, { 0 }, }; diff_expects *expected; int i, j; g_repo = cl_git_sandbox_init("attr"); cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); cl_assert((c = resolve_commit_oid_to_tree(g_repo, c_commit)) != NULL); cl_assert((d = resolve_commit_oid_to_tree(g_repo, d_commit)) != NULL); for (i = 0; test_expects[i].files > 0; i++) { memset(&actual, 0, sizeof(actual)); /* clear accumulator */ opts = test_options[i]; if (test_ab_or_cd[i] == 0) cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts)); else cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, c, d, &opts)); cl_git_pass(git_diff_foreach( diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &actual)); expected = &test_expects[i]; cl_assert_equal_i(actual.files, expected->files); for (j = GIT_DELTA_UNMODIFIED; j <= GIT_DELTA_TYPECHANGE; ++j) cl_assert_equal_i(expected->file_status[j], actual.file_status[j]); cl_assert_equal_i(actual.hunks, expected->hunks); cl_assert_equal_i(actual.lines, expected->lines); cl_assert_equal_i(actual.line_ctxt, expected->line_ctxt); cl_assert_equal_i(actual.line_adds, expected->line_adds); cl_assert_equal_i(actual.line_dels, expected->line_dels); git_diff_free(diff); diff = NULL; } git_tree_free(c); git_tree_free(d); }