Ejemplo n.º 1
0
void test_diff_diffiter__iterate_and_generate_patch_text(void)
{
	git_repository *repo = cl_git_sandbox_init("status");
	git_diff_list *diff;
	size_t d, num_d;

	cl_git_pass(git_diff_workdir_to_index(repo, NULL, &diff));

	num_d = git_diff_num_deltas(diff);
	cl_assert_equal_i(8, (int)num_d);

	for (d = 0; d < num_d; ++d) {
		git_diff_patch *patch;
		char *text;

		cl_git_pass(git_diff_get_patch(&patch, NULL, diff, d));
		cl_assert(patch != NULL);

		cl_git_pass(git_diff_patch_to_str(&text, patch));

		cl_assert_equal_s(expected_patch_text[d], text);

		git__free(text);
		git_diff_patch_free(patch);
	}

	git_diff_list_free(diff);
}
Ejemplo n.º 2
0
void test_diff_workdir__filemode_changes_with_filemode_false(void)
{
	git_config *cfg;
	git_diff_list *diff = NULL;
	diff_expects exp;

	if (!cl_is_chmod_supported())
		return;

	g_repo = cl_git_sandbox_init("issue_592");

	cl_git_pass(git_repository_config(&cfg, g_repo));
	cl_git_pass(git_config_set_bool(cfg, "core.filemode", false));

	/* test once with no mods */

	cl_git_pass(git_diff_workdir_to_index(g_repo, NULL, &diff));

	memset(&exp, 0, sizeof(exp));
	cl_git_pass(git_diff_foreach(
		diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));

	cl_assert_equal_i(0, exp.files);
	cl_assert_equal_i(0, exp.file_mods);
	cl_assert_equal_i(0, exp.hunks);

	git_diff_list_free(diff);

	/* chmod file and test again */

	cl_assert(cl_toggle_filemode("issue_592/a.txt"));

	cl_git_pass(git_diff_workdir_to_index(g_repo, NULL, &diff));

	memset(&exp, 0, sizeof(exp));
	cl_git_pass(git_diff_foreach(
		diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));

	cl_assert_equal_i(0, exp.files);
	cl_assert_equal_i(0, exp.file_mods);
	cl_assert_equal_i(0, exp.hunks);

	git_diff_list_free(diff);

	cl_assert(cl_toggle_filemode("issue_592/a.txt"));
	git_config_free(cfg);
}
Ejemplo n.º 3
0
void test_diff_diffiter__iterate_all(void)
{
	git_repository *repo = cl_git_sandbox_init("status");
	git_diff_options opts = {0};
	git_diff_list *diff = NULL;
	diff_expects exp = {0};
	size_t d, num_d;

	opts.context_lines = 3;
	opts.interhunk_lines = 1;
	opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;

	cl_git_pass(git_diff_workdir_to_index(repo, &opts, &diff));

	num_d = git_diff_num_deltas(diff);
	for (d = 0; d < num_d; ++d) {
		git_diff_patch *patch;
		const git_diff_delta *delta;
		size_t h, num_h;

		cl_git_pass(git_diff_get_patch(&patch, &delta, diff, d));
		cl_assert(patch && delta);
		exp.files++;

		num_h = git_diff_patch_num_hunks(patch);
		for (h = 0; h < num_h; h++) {
			const git_diff_range *range;
			const char *header;
			size_t header_len, l, num_l;

			cl_git_pass(git_diff_patch_get_hunk(
				&range, &header, &header_len, &num_l, patch, h));
			cl_assert(range && header);
			exp.hunks++;

			for (l = 0; l < num_l; ++l) {
				char origin;
				const char *content;
				size_t content_len;

				cl_git_pass(git_diff_patch_get_line_in_hunk(
					&origin, &content, &content_len, NULL, NULL, patch, h, l));
				cl_assert(content);
				exp.lines++;
			}
		}

		git_diff_patch_free(patch);
	}

	cl_assert_equal_i(13, exp.files);
	cl_assert_equal_i(8, exp.hunks);
	cl_assert_equal_i(14, exp.lines);

	git_diff_list_free(diff);
}
Ejemplo n.º 4
0
void test_diff_diffiter__iterate_files_and_hunks(void)
{
	git_repository *repo = cl_git_sandbox_init("status");
	git_diff_options opts = {0};
	git_diff_list *diff = NULL;
	size_t d, num_d;
	int file_count = 0, hunk_count = 0;

	opts.context_lines = 3;
	opts.interhunk_lines = 1;
	opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;

	cl_git_pass(git_diff_workdir_to_index(repo, &opts, &diff));

	num_d = git_diff_num_deltas(diff);

	for (d = 0; d < num_d; ++d) {
		git_diff_patch *patch;
		const git_diff_delta *delta;
		size_t h, num_h;

		cl_git_pass(git_diff_get_patch(&patch, &delta, diff, d));

		cl_assert(delta);
		cl_assert(patch);

		file_count++;

		num_h = git_diff_patch_num_hunks(patch);

		for (h = 0; h < num_h; h++) {
			const git_diff_range *range;
			const char *header;
			size_t header_len, num_l;

			cl_git_pass(git_diff_patch_get_hunk(
				&range, &header, &header_len, &num_l, patch, h));

			cl_assert(range);
			cl_assert(header);

			hunk_count++;
		}

		git_diff_patch_free(patch);
	}

	cl_assert_equal_i(13, file_count);
	cl_assert_equal_i(8, hunk_count);

	git_diff_list_free(diff);
}
Ejemplo n.º 5
0
void test_diff_workdir__to_index(void)
{
	git_diff_options opts = {0};
	git_diff_list *diff = NULL;
	diff_expects exp;
	int use_iterator;

	g_repo = cl_git_sandbox_init("status");

	opts.context_lines = 3;
	opts.interhunk_lines = 1;
	opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;

	cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff));

	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
		memset(&exp, 0, sizeof(exp));

		if (use_iterator)
			cl_git_pass(diff_foreach_via_iterator(
				diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
		else
			cl_git_pass(git_diff_foreach(
				diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));

		/* to generate these values:
		 * - cd to tests/resources/status,
		 * - mv .gitted .git
		 * - git diff --name-status
		 * - git diff
		 * - mv .git .gitted
		 */
		cl_assert_equal_i(13, exp.files);
		cl_assert_equal_i(0, exp.file_adds);
		cl_assert_equal_i(4, exp.file_dels);
		cl_assert_equal_i(4, exp.file_mods);
		cl_assert_equal_i(1, exp.file_ignored);
		cl_assert_equal_i(4, exp.file_untracked);

		cl_assert_equal_i(8, exp.hunks);

		cl_assert_equal_i(14, exp.lines);
		cl_assert_equal_i(5, exp.line_ctxt);
		cl_assert_equal_i(4, exp.line_adds);
		cl_assert_equal_i(5, exp.line_dels);
	}

	git_diff_list_free(diff);
}
Ejemplo n.º 6
0
void test_diff_workdir__cannot_diff_against_a_bare_repository(void)
{
	git_diff_options opts = {0};
	git_diff_list *diff = NULL;
	git_tree *tree;

	g_repo = cl_git_sandbox_init("testrepo.git");

	cl_assert_equal_i(GIT_EBAREREPO, git_diff_workdir_to_index(g_repo, &opts, &diff));

	cl_git_pass(git_repository_head_tree(&tree, g_repo));
	cl_assert_equal_i(GIT_EBAREREPO, git_diff_workdir_to_tree(g_repo, &opts, tree, &diff));

	git_tree_free(tree);
}
Ejemplo n.º 7
0
void test_diff_diffiter__create(void)
{
	git_repository *repo = cl_git_sandbox_init("attr");
	git_diff_list *diff;
	size_t d, num_d;

	cl_git_pass(git_diff_workdir_to_index(repo, NULL, &diff));

	num_d = git_diff_num_deltas(diff);
	for (d = 0; d < num_d; ++d) {
		const git_diff_delta *delta;
		cl_git_pass(git_diff_get_patch(NULL, &delta, diff, d));
	}

	git_diff_list_free(diff);
}
Ejemplo n.º 8
0
Archivo: index.c Proyecto: guocb/pygit2
PyObject *
Index_diff_tree(Index *self, PyObject *args)
{
    git_diff_options opts = {0};
    git_diff_list *diff;
    int err;

    Diff *py_diff;
    PyObject *py_obj = NULL;

    if (!PyArg_ParseTuple(args, "|O", &py_obj))
        return NULL;

    if (py_obj == NULL) {
        err = git_diff_workdir_to_index(
                self->repo->repo,
                &opts,
                &diff);
    } else if (PyObject_TypeCheck(py_obj, &TreeType)) {
        err = git_diff_index_to_tree(
                self->repo->repo,
                &opts,
                ((Tree *)py_obj)->tree,
                &diff);
    } 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(py_diff);
        Py_INCREF(self->repo);
        py_diff->repo = self->repo;
        py_diff->diff = diff;
    }

    return (PyObject*)py_diff;
}
Ejemplo n.º 9
0
void test_diff_diffiter__iterate_files_2(void)
{
	git_repository *repo = cl_git_sandbox_init("status");
	git_diff_list *diff;
	size_t d, num_d;
	int count = 0;

	cl_git_pass(git_diff_workdir_to_index(repo, NULL, &diff));

	num_d = git_diff_num_deltas(diff);
	cl_assert_equal_i(8, (int)num_d);

	for (d = 0; d < num_d; ++d) {
		const git_diff_delta *delta;
		cl_git_pass(git_diff_get_patch(NULL, &delta, diff, d));
		cl_assert(delta != NULL);
		count++;
	}
	cl_assert_equal_i(8, count);

	git_diff_list_free(diff);
}
Ejemplo n.º 10
0
void test_diff_workdir__to_tree(void)
{
	/* grabbed a couple of commit oids from the history of the attr repo */
	const char *a_commit = "26a125ee1bf"; /* the current HEAD */
	const char *b_commit = "0017bd4ab1ec3"; /* the start */
	git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit);
	git_tree *b = resolve_commit_oid_to_tree(g_repo, b_commit);
	git_diff_options opts = {0};
	git_diff_list *diff = NULL;
	git_diff_list *diff2 = NULL;
	diff_expects exp;

	opts.context_lines = 3;
	opts.interhunk_lines = 1;
	opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;

	memset(&exp, 0, sizeof(exp));

	/* You can't really generate the equivalent of git_diff_workdir_to_tree()
	 * using C git.  It really wants to interpose the index into the diff.
	 *
	 * To validate the following results with command line git, I ran the
	 * following:
	 * - git ls-tree 26a125
	 * - find . ! -path ./.git/\* -a -type f | git hash-object --stdin-paths
	 * The results are documented at the bottom of this file in the
	 * long comment entitled "PREPARATION OF TEST DATA".
	 */
	cl_git_pass(git_diff_workdir_to_tree(g_repo, &opts, a, &diff));

	cl_git_pass(git_diff_foreach(
		diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));

	cl_assert(exp.files == 13);
	cl_assert(exp.file_adds == 0);
	cl_assert(exp.file_dels == 4);
	cl_assert(exp.file_mods == 4);
	cl_assert(exp.file_ignored == 1);
	cl_assert(exp.file_untracked == 4);

	/* Since there is no git diff equivalent, let's just assume that the
	 * text diffs produced by git_diff_foreach are accurate here.  We will
	 * do more apples-to-apples test comparison below.
	 */

	git_diff_list_free(diff);
	diff = NULL;
	memset(&exp, 0, sizeof(exp));

	/* This is a compatible emulation of "git diff <sha>" which looks like
	 * a workdir to tree diff (even though it is not really).  This is what
	 * you would get from "git diff --name-status 26a125ee1bf"
	 */
	cl_git_pass(git_diff_index_to_tree(g_repo, &opts, a, &diff));
	cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff2));
	cl_git_pass(git_diff_merge(diff, diff2));
	git_diff_list_free(diff2);

	cl_git_pass(git_diff_foreach(
		diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));

	cl_assert(exp.files == 14);
	cl_assert(exp.file_adds == 2);
	cl_assert(exp.file_dels == 5);
	cl_assert(exp.file_mods == 4);
	cl_assert(exp.file_ignored == 1);
	cl_assert(exp.file_untracked == 2);

	cl_assert(exp.hunks == 11);

	cl_assert(exp.lines == 17);
	cl_assert(exp.line_ctxt == 4);
	cl_assert(exp.line_adds == 8);
	cl_assert(exp.line_dels == 5);

	git_diff_list_free(diff);
	diff = NULL;
	memset(&exp, 0, sizeof(exp));

	/* Again, emulating "git diff <sha>" for testing purposes using
	 * "git diff --name-status 0017bd4ab1ec3" instead.
	 */
	cl_git_pass(git_diff_index_to_tree(g_repo, &opts, b, &diff));
	cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff2));
	cl_git_pass(git_diff_merge(diff, diff2));
	git_diff_list_free(diff2);

	cl_git_pass(git_diff_foreach(
		diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));

	cl_assert(exp.files == 15);
	cl_assert(exp.file_adds == 5);
	cl_assert(exp.file_dels == 4);
	cl_assert(exp.file_mods == 3);
	cl_assert(exp.file_ignored == 1);
	cl_assert(exp.file_untracked == 2);

	cl_assert(exp.hunks == 12);

	cl_assert(exp.lines == 19);
	cl_assert(exp.line_ctxt == 3);
	cl_assert(exp.line_adds == 12);
	cl_assert(exp.line_dels == 4);

	git_diff_list_free(diff);

	git_tree_free(a);
	git_tree_free(b);
}
Ejemplo n.º 11
0
void test_diff_workdir__to_index_with_pathspec(void)
{
	git_diff_options opts = {0};
	git_diff_list *diff = NULL;
	diff_expects exp;
	char *pathspec = NULL;

	opts.context_lines = 3;
	opts.interhunk_lines = 1;
	opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
	opts.pathspec.strings = &pathspec;
	opts.pathspec.count   = 1;

	memset(&exp, 0, sizeof(exp));

	cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff));
	cl_git_pass(git_diff_foreach(diff, &exp, diff_file_fn, NULL, NULL));

	cl_assert_equal_i(12, exp.files);
	cl_assert_equal_i(0, exp.file_adds);
	cl_assert_equal_i(4, exp.file_dels);
	cl_assert_equal_i(4, exp.file_mods);
	cl_assert_equal_i(1, exp.file_ignored);
	cl_assert_equal_i(3, exp.file_untracked);

	git_diff_list_free(diff);

	memset(&exp, 0, sizeof(exp));
	pathspec = "modified_file";

	cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff));
	cl_git_pass(git_diff_foreach(diff, &exp, diff_file_fn, NULL, NULL));

	cl_assert_equal_i(1, exp.files);
	cl_assert_equal_i(0, exp.file_adds);
	cl_assert_equal_i(0, exp.file_dels);
	cl_assert_equal_i(1, exp.file_mods);
	cl_assert_equal_i(0, exp.file_ignored);
	cl_assert_equal_i(0, exp.file_untracked);

	git_diff_list_free(diff);

	memset(&exp, 0, sizeof(exp));
	pathspec = "subdir";

	cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff));
	cl_git_pass(git_diff_foreach(diff, &exp, diff_file_fn, NULL, NULL));

	cl_assert_equal_i(3, exp.files);
	cl_assert_equal_i(0, exp.file_adds);
	cl_assert_equal_i(1, exp.file_dels);
	cl_assert_equal_i(1, exp.file_mods);
	cl_assert_equal_i(0, exp.file_ignored);
	cl_assert_equal_i(1, exp.file_untracked);

	git_diff_list_free(diff);

	memset(&exp, 0, sizeof(exp));
	pathspec = "*_deleted";

	cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff));
	cl_git_pass(git_diff_foreach(diff, &exp, diff_file_fn, NULL, NULL));

	cl_assert_equal_i(2, exp.files);
	cl_assert_equal_i(0, exp.file_adds);
	cl_assert_equal_i(2, exp.file_dels);
	cl_assert_equal_i(0, exp.file_mods);
	cl_assert_equal_i(0, exp.file_ignored);
	cl_assert_equal_i(0, exp.file_untracked);

	git_diff_list_free(diff);
}
Ejemplo n.º 12
0
int git_checkout_index(
	git_repository *repo,
	git_checkout_opts *opts,
	git_indexer_stats *stats)
{
	git_diff_list *diff = NULL;
	git_indexer_stats dummy_stats;

	git_diff_options diff_opts = {0};
	git_checkout_opts checkout_opts;

	struct checkout_diff_data data;
	git_buf workdir = GIT_BUF_INIT;

	int error;

	assert(repo);

	if ((error = git_repository__ensure_not_bare(repo, "checkout")) < 0)
		return error;

	diff_opts.flags =
		GIT_DIFF_INCLUDE_UNTRACKED |
		GIT_DIFF_INCLUDE_TYPECHANGE |
		GIT_DIFF_SKIP_BINARY_CHECK;

	if (opts && opts->paths.count > 0)
		diff_opts.pathspec = opts->paths;

	if ((error = git_diff_workdir_to_index(repo, &diff_opts, &diff)) < 0)
		goto cleanup;

	if ((error = git_buf_puts(&workdir, git_repository_workdir(repo))) < 0)
		goto cleanup;

	normalize_options(&checkout_opts, opts);

	if (!stats)
		stats = &dummy_stats;

	stats->processed = 0;
	/* total based on 3 passes, but it might be 2 if no submodules */
	stats->total = (unsigned int)git_diff_num_deltas(diff) * 3;

	memset(&data, 0, sizeof(data));

	data.path = &workdir;
	data.workdir_len = git_buf_len(&workdir);
	data.checkout_opts = &checkout_opts;
	data.stats = stats;
	data.owner = repo;

	if ((error = retrieve_symlink_capabilities(repo, &data.can_symlink)) < 0)
		goto cleanup;

	/* Checkout is best performed with three passes through the diff.
	 *
	 * 1. First do removes, because we iterate in alphabetical order, thus
	 *    a new untracked directory will end up sorted *after* a blob that
	 *    should be checked out with the same name.
	 * 2. Then checkout all blobs.
	 * 3. Then checkout all submodules in case a new .gitmodules blob was
	 *    checked out during pass #2.
	 */

	if (!(error = git_diff_foreach(
			diff, &data, checkout_remove_the_old, NULL, NULL)) &&
		!(error = git_diff_foreach(
			diff, &data, checkout_create_the_new, NULL, NULL)) &&
		data.found_submodules)
	{
		data.create_submodules = true;
		error = git_diff_foreach(
			diff, &data, checkout_create_the_new, NULL, NULL);
	}

	stats->processed = stats->total;

cleanup:
	if (error == GIT_EUSER)
		error = (data.error != 0) ? data.error : -1;

	git_diff_list_free(diff);
	git_buf_free(&workdir);

	return error;
}
Ejemplo n.º 13
0
void test_diff_workdir__head_index_and_workdir_all_differ(void)
{
	git_diff_options opts = {0};
	git_diff_list *diff_i2t = NULL, *diff_w2i = NULL;
	diff_expects exp;
	char *pathspec = "staged_changes_modified_file";
	git_tree *tree;
	int use_iterator;

	/* For this file,
	 * - head->index diff has 1 line of context, 1 line of diff
	 * - index->workdir diff has 2 lines of context, 1 line of diff
	 * but
	 * - head->workdir diff has 1 line of context, 2 lines of diff
	 * Let's make sure the right one is returned from each fn.
	 */

	g_repo = cl_git_sandbox_init("status");

	tree = resolve_commit_oid_to_tree(g_repo, "26a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f");

	opts.pathspec.strings = &pathspec;
	opts.pathspec.count   = 1;

	cl_git_pass(git_diff_index_to_tree(g_repo, &opts, tree, &diff_i2t));
	cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff_w2i));

	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
		memset(&exp, 0, sizeof(exp));

		if (use_iterator)
			cl_git_pass(diff_foreach_via_iterator(
				diff_i2t, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
		else
			cl_git_pass(git_diff_foreach(
				diff_i2t, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));

		cl_assert_equal_i(1, exp.files);
		cl_assert_equal_i(0, exp.file_adds);
		cl_assert_equal_i(0, exp.file_dels);
		cl_assert_equal_i(1, exp.file_mods);
		cl_assert_equal_i(1, exp.hunks);
		cl_assert_equal_i(2, exp.lines);
		cl_assert_equal_i(1, exp.line_ctxt);
		cl_assert_equal_i(1, exp.line_adds);
		cl_assert_equal_i(0, exp.line_dels);
	}

	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
		memset(&exp, 0, sizeof(exp));

		if (use_iterator)
			cl_git_pass(diff_foreach_via_iterator(
				diff_w2i, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
		else
			cl_git_pass(git_diff_foreach(
				diff_w2i, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));

		cl_assert_equal_i(1, exp.files);
		cl_assert_equal_i(0, exp.file_adds);
		cl_assert_equal_i(0, exp.file_dels);
		cl_assert_equal_i(1, exp.file_mods);
		cl_assert_equal_i(1, exp.hunks);
		cl_assert_equal_i(3, exp.lines);
		cl_assert_equal_i(2, exp.line_ctxt);
		cl_assert_equal_i(1, exp.line_adds);
		cl_assert_equal_i(0, exp.line_dels);
	}

	cl_git_pass(git_diff_merge(diff_i2t, diff_w2i));

	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
		memset(&exp, 0, sizeof(exp));

		if (use_iterator)
			cl_git_pass(diff_foreach_via_iterator(
				diff_i2t, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
		else
			cl_git_pass(git_diff_foreach(
				diff_i2t, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));

		cl_assert_equal_i(1, exp.files);
		cl_assert_equal_i(0, exp.file_adds);
		cl_assert_equal_i(0, exp.file_dels);
		cl_assert_equal_i(1, exp.file_mods);
		cl_assert_equal_i(1, exp.hunks);
		cl_assert_equal_i(3, exp.lines);
		cl_assert_equal_i(1, exp.line_ctxt);
		cl_assert_equal_i(2, exp.line_adds);
		cl_assert_equal_i(0, exp.line_dels);
	}

	git_diff_list_free(diff_i2t);
	git_diff_list_free(diff_w2i);

	git_tree_free(tree);
}
Ejemplo n.º 14
0
void test_diff_workdir__eof_newline_changes(void)
{
	git_diff_options opts = {0};
	git_diff_list *diff = NULL;
	diff_expects exp;
	char *pathspec = "current_file";
	int use_iterator;

	g_repo = cl_git_sandbox_init("status");

	opts.pathspec.strings = &pathspec;
	opts.pathspec.count   = 1;

	cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff));

	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
		memset(&exp, 0, sizeof(exp));

		if (use_iterator)
			cl_git_pass(diff_foreach_via_iterator(
				diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
		else
			cl_git_pass(git_diff_foreach(
				diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));

		cl_assert_equal_i(0, exp.files);
		cl_assert_equal_i(0, exp.file_adds);
		cl_assert_equal_i(0, exp.file_dels);
		cl_assert_equal_i(0, exp.file_mods);
		cl_assert_equal_i(0, exp.hunks);
		cl_assert_equal_i(0, exp.lines);
		cl_assert_equal_i(0, exp.line_ctxt);
		cl_assert_equal_i(0, exp.line_adds);
		cl_assert_equal_i(0, exp.line_dels);
	}

	git_diff_list_free(diff);

	cl_git_append2file("status/current_file", "\n");

	cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff));

	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
		memset(&exp, 0, sizeof(exp));

		if (use_iterator)
			cl_git_pass(diff_foreach_via_iterator(
				diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
		else
			cl_git_pass(git_diff_foreach(
				diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));

		cl_assert_equal_i(1, exp.files);
		cl_assert_equal_i(0, exp.file_adds);
		cl_assert_equal_i(0, exp.file_dels);
		cl_assert_equal_i(1, exp.file_mods);
		cl_assert_equal_i(1, exp.hunks);
		cl_assert_equal_i(2, exp.lines);
		cl_assert_equal_i(1, exp.line_ctxt);
		cl_assert_equal_i(1, exp.line_adds);
		cl_assert_equal_i(0, exp.line_dels);
	}

	git_diff_list_free(diff);

	cl_git_rewritefile("status/current_file", "current_file");

	cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff));

	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
		memset(&exp, 0, sizeof(exp));

		if (use_iterator)
			cl_git_pass(diff_foreach_via_iterator(
				diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));
		else
			cl_git_pass(git_diff_foreach(
				diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn));

		cl_assert_equal_i(1, exp.files);
		cl_assert_equal_i(0, exp.file_adds);
		cl_assert_equal_i(0, exp.file_dels);
		cl_assert_equal_i(1, exp.file_mods);
		cl_assert_equal_i(1, exp.hunks);
		cl_assert_equal_i(3, exp.lines);
		cl_assert_equal_i(0, exp.line_ctxt);
		cl_assert_equal_i(1, exp.line_adds);
		cl_assert_equal_i(2, exp.line_dels);
	}

	git_diff_list_free(diff);
}
Ejemplo n.º 15
0
void test_diff_diffiter__iterate_randomly_while_saving_state(void)
{
	git_repository *repo = cl_git_sandbox_init("status");
	git_diff_options opts = {0};
	git_diff_list *diff = NULL;
	diff_expects exp = {0};
	git_diff_patch *patches[PATCH_CACHE];
	size_t p, d, num_d;

	memset(patches, 0, sizeof(patches));

	opts.context_lines = 3;
	opts.interhunk_lines = 1;
	opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;

	cl_git_pass(git_diff_workdir_to_index(repo, &opts, &diff));

	num_d = git_diff_num_deltas(diff);

	/* To make sure that references counts work for diff and patch objects,
	 * this generates patches and randomly caches them.  Only when the patch
	 * is removed from the cache are hunks and lines counted.  At the end,
	 * there are still patches in the cache, so free the diff and try to
	 * process remaining patches after the diff is freed.
	 */

	srand(121212);
	p = rand() % PATCH_CACHE;

	for (d = 0; d < num_d; ++d) {
		/* take old patch */
		git_diff_patch *patch = patches[p];
		patches[p] = NULL;

		/* cache new patch */
		cl_git_pass(git_diff_get_patch(&patches[p], NULL, diff, d));
		cl_assert(patches[p] != NULL);

		/* process old patch if non-NULL */
		if (patch != NULL) {
			iterate_over_patch(patch, &exp);
			git_diff_patch_free(patch);
		}

		p = rand() % PATCH_CACHE;
	}

	/* free diff list now - refcounts should keep things safe */
	git_diff_list_free(diff);

	/* process remaining unprocessed patches */
	for (p = 0; p < PATCH_CACHE; p++) {
		git_diff_patch *patch = patches[p];

		if (patch != NULL) {
			iterate_over_patch(patch, &exp);
			git_diff_patch_free(patch);
		}
	}

	/* hopefully it all still added up right */
	cl_assert_equal_i(13, exp.files);
	cl_assert_equal_i(8, exp.hunks);
	cl_assert_equal_i(14, exp.lines);
}
Ejemplo n.º 16
0
void test_diff_workdir__larger_hunks(void)
{
	const char *a_commit = "d70d245ed97ed2aa596dd1af6536e4bfdb047b69";
	const char *b_commit = "7a9e0b02e63179929fed24f0a3e0f19168114d10";
	git_tree *a, *b;
	git_diff_options opts = {0};
	size_t i, d, num_d, h, num_h, l, num_l, header_len, line_len;

	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;

	for (i = 0; i <= 2; ++i) {
		git_diff_list *diff = NULL;
		git_diff_patch *patch;
		const git_diff_range *range;
		const char *header, *line;
		char origin;

		/* okay, this is a bit silly, but oh well */
		switch (i) {
		case 0:
			cl_git_pass(git_diff_workdir_to_index(g_repo, &opts, &diff));
			break;
		case 1:
			cl_git_pass(git_diff_workdir_to_tree(g_repo, &opts, a, &diff));
			break;
		case 2:
			cl_git_pass(git_diff_workdir_to_tree(g_repo, &opts, b, &diff));
			break;
		}

		num_d = git_diff_num_deltas(diff);
		cl_assert_equal_i(2, (int)num_d);

		for (d = 0; d < num_d; ++d) {
			cl_git_pass(git_diff_get_patch(&patch, NULL, diff, d));
			cl_assert(patch);

			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);
				}

				/* confirm fail after the last item */
				cl_git_fail(git_diff_patch_get_line_in_hunk(
					&origin, &line, &line_len, NULL, NULL, patch, h, num_l));
			}

			/* confirm fail after the last item */
			cl_git_fail(git_diff_patch_get_hunk(
				&range, &header, &header_len, &num_l, patch, num_h));

			git_diff_patch_free(patch);
		}

		git_diff_list_free(diff);
	}

	git_tree_free(a);
	git_tree_free(b);
}
Ejemplo n.º 17
0
void test_diff_diffiter__max_size_threshold(void)
{
	git_repository *repo = cl_git_sandbox_init("status");
	git_diff_options opts = {0};
	git_diff_list *diff = NULL;
	int file_count = 0, binary_count = 0, hunk_count = 0;
	size_t d, num_d;

	opts.context_lines = 3;
	opts.interhunk_lines = 1;
	opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;

	cl_git_pass(git_diff_workdir_to_index(repo, &opts, &diff));
	num_d = git_diff_num_deltas(diff);

	for (d = 0; d < num_d; ++d) {
		git_diff_patch *patch;
		const git_diff_delta *delta;

		cl_git_pass(git_diff_get_patch(&patch, &delta, diff, d));
		cl_assert(delta);
		cl_assert(patch);

		file_count++;
		hunk_count += (int)git_diff_patch_num_hunks(patch);

		assert(delta->binary == 0 || delta->binary == 1);
		binary_count += delta->binary;

		git_diff_patch_free(patch);
	}

	cl_assert_equal_i(13, file_count);
	cl_assert_equal_i(0, binary_count);
	cl_assert_equal_i(8, hunk_count);

	git_diff_list_free(diff);

	/* try again with low file size threshold */

	file_count = binary_count = hunk_count = 0;

	opts.context_lines = 3;
	opts.interhunk_lines = 1;
	opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
	opts.max_size = 50; /* treat anything over 50 bytes as binary! */

	cl_git_pass(git_diff_workdir_to_index(repo, &opts, &diff));
	num_d = git_diff_num_deltas(diff);

	for (d = 0; d < num_d; ++d) {
		git_diff_patch *patch;
		const git_diff_delta *delta;

		cl_git_pass(git_diff_get_patch(&patch, &delta, diff, d));

		file_count++;
		hunk_count += (int)git_diff_patch_num_hunks(patch);

		assert(delta->binary == 0 || delta->binary == 1);
		binary_count += delta->binary;

		git_diff_patch_free(patch);
	}

	cl_assert_equal_i(13, file_count);
	/* Three files are over the 50 byte threshold:
	 * - staged_changes_file_deleted
	 * - staged_changes_modified_file
	 * - staged_new_file_modified_file
	 */
	cl_assert_equal_i(3, binary_count);
	cl_assert_equal_i(5, hunk_count);

	git_diff_list_free(diff);
}