示例#1
0
文件: tree.c 项目: Angeldude/sonic-pi
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);
}
示例#2
0
文件: tree.c 项目: heynemann/pygit2
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);
}
示例#4
0
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);
}
示例#5
0
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);
}
示例#6
0
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; 
}
示例#7
0
文件: tree.c 项目: Angeldude/sonic-pi
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);
}
示例#8
0
 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);
}
示例#10
0
文件: tree.c 项目: Angeldude/sonic-pi
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);
}
示例#11
0
文件: tree.c 项目: Angeldude/sonic-pi
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();
}
示例#12
0
文件: tree.c 项目: Angeldude/sonic-pi
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));
}
示例#13
0
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;
}
示例#14
0
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);
}
示例#15
0
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);
}
示例#16
0
文件: tree.c 项目: Angeldude/sonic-pi
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);
}
示例#17
0
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();
}
示例#18
0
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();
}
示例#19
0
文件: tree.c 项目: Asquera/libgit2
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);
}
示例#20
0
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);
}
示例#21
0
文件: tree.c 项目: Angeldude/sonic-pi
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]);
}
示例#22
0
文件: diff.c 项目: jwes/luagi
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;
}
示例#23
0
/* 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;
}
示例#24
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);
}
示例#25
0
文件: qgit.cpp 项目: bokic/gitmaster
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);
}
示例#26
0
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;
}
示例#27
0
文件: qgit.cpp 项目: bokic/gitmaster
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;
    }
}
示例#28
0
文件: tree.c 项目: Angeldude/sonic-pi
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);
}
示例#29
0
文件: diff.c 项目: ethomson/libgit2
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:
	 *
	 *  * &lt;sha1&gt; &lt;sha2&gt;
	 *  * &lt;sha1&gt; --cached
	 *  * &lt;sha1&gt;
	 *  * --cached
	 *  * --nocache (don't use index data in diff at all)
	 *  * nothing
	 *
	 * Currently ranged arguments like &lt;sha1&gt;..&lt;sha2&gt; and &lt;sha1&gt;...&lt;sha2&gt;
	 * 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;
}
示例#30
0
文件: tree.c 项目: Angeldude/sonic-pi
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);
}