Blame tests/diff/workdir.c

Packit Service 20376f
#include "clar_libgit2.h"
Packit Service 20376f
#include "diff_helpers.h"
Packit Service 20376f
#include "repository.h"
Packit Service 20376f
#include "git2/sys/diff.h"
Packit Service 20376f
#include "../checkout/checkout_helpers.h"
Packit Service 20376f
Packit Service 20376f
static git_repository *g_repo = NULL;
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__cleanup(void)
Packit Service 20376f
{
Packit Service 20376f
	cl_git_sandbox_cleanup();
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__to_index(void)
Packit Service 20376f
{
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_diff *diff = NULL;
Packit Service 20376f
	diff_expects exp;
Packit Service 20376f
	int use_iterator;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("status");
Packit Service 20376f
Packit Service 20376f
	opts.context_lines = 3;
Packit Service 20376f
	opts.interhunk_lines = 1;
Packit Service 20376f
	opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(
Packit Service 20376f
				diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
		/* to generate these values:
Packit Service 20376f
		 * - cd to tests/resources/status,
Packit Service 20376f
		 * - mv .gitted .git
Packit Service 20376f
		 * - git diff --name-status
Packit Service 20376f
		 * - git diff
Packit Service 20376f
		 * - mv .git .gitted
Packit Service 20376f
		 */
Packit Service 20376f
		cl_assert_equal_i(13, exp.files);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
		cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(8, exp.hunks);
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(14, exp.lines);
Packit Service 20376f
		cl_assert_equal_i(5, exp.line_ctxt);
Packit Service 20376f
		cl_assert_equal_i(4, exp.line_adds);
Packit Service 20376f
		cl_assert_equal_i(5, exp.line_dels);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	{
Packit Service 20376f
		git_diff_perfdata perf = GIT_DIFF_PERFDATA_INIT;
Packit Service 20376f
		cl_git_pass(git_diff_get_perfdata(&perf, diff));
Packit Service 20376f
		cl_assert_equal_sz(
Packit Service 20376f
			13 /* in root */ + 3 /* in subdir */, perf.stat_calls);
Packit Service 20376f
		cl_assert_equal_sz(5, perf.oid_calculations);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__to_index_with_conflicts(void)
Packit Service 20376f
{
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_diff *diff = NULL;
Packit Service 20376f
	git_index *index;
Packit Service 20376f
	git_index_entry our_entry = {{0}}, their_entry = {{0}};
Packit Service 20376f
	diff_expects exp = {0};
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("status");
Packit Service 20376f
Packit Service 20376f
	opts.context_lines = 3;
Packit Service 20376f
	opts.interhunk_lines = 1;
Packit Service 20376f
Packit Service 20376f
	/* Adding an entry that represents a rename gets two files in conflict */
Packit Service 20376f
	our_entry.path = "subdir/modified_file";
Packit Service 20376f
	our_entry.mode = 0100644;
Packit Service 20376f
	git_oid_fromstr(&our_entry.id, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf");
Packit Service 20376f
Packit Service 20376f
	their_entry.path = "subdir/rename_conflict";
Packit Service 20376f
	their_entry.mode = 0100644;
Packit Service 20376f
	git_oid_fromstr(&their_entry.id, "2bd0a343aeef7a2cf0d158478966a6e587ff3863");
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_repository_index(&index, g_repo));
Packit Service 20376f
	cl_git_pass(git_index_conflict_add(index, NULL, &our_entry, &their_entry));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, &opts));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
		diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(9, exp.files);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
	cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
	cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
	cl_assert_equal_i(2, exp.file_status[GIT_DELTA_CONFLICTED]);
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(7, exp.hunks);
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(12, exp.lines);
Packit Service 20376f
	cl_assert_equal_i(4, exp.line_ctxt);
Packit Service 20376f
	cl_assert_equal_i(3, exp.line_adds);
Packit Service 20376f
	cl_assert_equal_i(5, exp.line_dels);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
	git_index_free(index);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__to_index_with_assume_unchanged(void)
Packit Service 20376f
{
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_diff *diff = NULL;
Packit Service 20376f
	git_index *idx = NULL;
Packit Service 20376f
	diff_expects exp;
Packit Service 20376f
	const git_index_entry *iep;
Packit Service 20376f
	git_index_entry ie;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("status");
Packit Service 20376f
Packit Service 20376f
	/* do initial diff */
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
	cl_git_pass(git_diff_foreach(
Packit Service 20376f
		diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
	cl_assert_equal_i(8, exp.files);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
	cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
	cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* mark a couple of entries with ASSUME_UNCHANGED */
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_repository_index(&idx, g_repo));
Packit Service 20376f
Packit Service 20376f
	cl_assert((iep = git_index_get_bypath(idx, "modified_file", 0)) != NULL);
Packit Service 20376f
	memcpy(&ie, iep, sizeof(ie));
Packit Service 20376f
	ie.flags |= GIT_IDXENTRY_VALID;
Packit Service 20376f
	cl_git_pass(git_index_add(idx, &ie);;
Packit Service 20376f
Packit Service 20376f
	cl_assert((iep = git_index_get_bypath(idx, "file_deleted", 0)) != NULL);
Packit Service 20376f
	memcpy(&ie, iep, sizeof(ie));
Packit Service 20376f
	ie.flags |= GIT_IDXENTRY_VALID;
Packit Service 20376f
	cl_git_pass(git_index_add(idx, &ie);;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_index_write(idx));
Packit Service 20376f
	git_index_free(idx);
Packit Service 20376f
Packit Service 20376f
	/* redo diff and see that entries are skipped */
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
	cl_git_pass(git_diff_foreach(
Packit Service 20376f
		diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
	cl_assert_equal_i(6, exp.files);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
	cl_assert_equal_i(3, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
	cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__to_tree(void)
Packit Service 20376f
{
Packit Service 20376f
	/* grabbed a couple of commit oids from the history of the attr repo */
Packit Service 20376f
	const char *a_commit = "26a125ee1bf"; /* the current HEAD */
Packit Service 20376f
	const char *b_commit = "0017bd4ab1ec3"; /* the start */
Packit Service 20376f
	git_tree *a, *b;
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_diff *diff = NULL;
Packit Service 20376f
	git_diff *diff2 = NULL;
Packit Service 20376f
	diff_expects exp;
Packit Service 20376f
	int use_iterator;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("status");
Packit Service 20376f
Packit Service 20376f
	a = resolve_commit_oid_to_tree(g_repo, a_commit);
Packit Service 20376f
	b = resolve_commit_oid_to_tree(g_repo, b_commit);
Packit Service 20376f
Packit Service 20376f
	opts.context_lines = 3;
Packit Service 20376f
	opts.interhunk_lines = 1;
Packit Service 20376f
	opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
Packit Service 20376f
Packit Service 20376f
	/* You can't really generate the equivalent of git_diff_tree_to_workdir()
Packit Service 20376f
	 * using C git.  It really wants to interpose the index into the diff.
Packit Service 20376f
	 *
Packit Service 20376f
	 * To validate the following results with command line git, I ran the
Packit Service 20376f
	 * following:
Packit Service 20376f
	 * - git ls-tree 26a125
Packit Service 20376f
	 * - find . ! -path ./.git/\* -a -type f | git hash-object --stdin-paths
Packit Service 20376f
	 * The results are documented at the bottom of this file in the
Packit Service 20376f
	 * long comment entitled "PREPARATION OF TEST DATA".
Packit Service 20376f
	 */
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, a, &opts));
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(
Packit Service 20376f
				diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(14, exp.files);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
		cl_assert_equal_i(5, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	/* Since there is no git diff equivalent, let's just assume that the
Packit Service 20376f
	 * text diffs produced by git_diff_foreach are accurate here.  We will
Packit Service 20376f
	 * do more apples-to-apples test comparison below.
Packit Service 20376f
	 */
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
	diff = NULL;
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
	/* This is a compatible emulation of "git diff <sha>" which looks like
Packit Service 20376f
	 * a workdir to tree diff (even though it is not really).  This is what
Packit Service 20376f
	 * you would get from "git diff --name-status 26a125ee1bf"
Packit Service 20376f
	 */
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts));
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, NULL, &opts));
Packit Service 20376f
	cl_git_pass(git_diff_merge(diff, diff2));
Packit Service 20376f
	git_diff_free(diff2);
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(
Packit Service 20376f
				diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(15, exp.files);
Packit Service 20376f
		cl_assert_equal_i(2, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(5, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
		cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(11, exp.hunks);
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(17, exp.lines);
Packit Service 20376f
		cl_assert_equal_i(4, exp.line_ctxt);
Packit Service 20376f
		cl_assert_equal_i(8, exp.line_adds);
Packit Service 20376f
		cl_assert_equal_i(5, exp.line_dels);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
	diff = NULL;
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
	/* Again, emulating "git diff <sha>" for testing purposes using
Packit Service 20376f
	 * "git diff --name-status 0017bd4ab1ec3" instead.
Packit Service 20376f
	 */
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_index(&diff, g_repo, b, NULL, &opts));
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, NULL, &opts));
Packit Service 20376f
	cl_git_pass(git_diff_merge(diff, diff2));
Packit Service 20376f
	git_diff_free(diff2);
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(
Packit Service 20376f
				diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(16, exp.files);
Packit Service 20376f
		cl_assert_equal_i(5, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
		cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(12, exp.hunks);
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(19, exp.lines);
Packit Service 20376f
		cl_assert_equal_i(3, exp.line_ctxt);
Packit Service 20376f
		cl_assert_equal_i(12, exp.line_adds);
Packit Service 20376f
		cl_assert_equal_i(4, exp.line_dels);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* Let's try that once more with a reversed diff */
Packit Service 20376f
Packit Service 20376f
	opts.flags |= GIT_DIFF_REVERSE;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_index(&diff, g_repo, b, NULL, &opts));
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, NULL, &opts));
Packit Service 20376f
	cl_git_pass(git_diff_merge(diff, diff2));
Packit Service 20376f
	git_diff_free(diff2);
Packit Service 20376f
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_foreach(
Packit Service 20376f
		diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(16, exp.files);
Packit Service 20376f
	cl_assert_equal_i(5, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
	cl_assert_equal_i(4, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
	cl_assert_equal_i(3, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
	cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(12, exp.hunks);
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(19, exp.lines);
Packit Service 20376f
	cl_assert_equal_i(3, exp.line_ctxt);
Packit Service 20376f
	cl_assert_equal_i(12, exp.line_dels);
Packit Service 20376f
	cl_assert_equal_i(4, exp.line_adds);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* all done now */
Packit Service 20376f
Packit Service 20376f
	git_tree_free(a);
Packit Service 20376f
	git_tree_free(b);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__to_index_with_pathspec(void)
Packit Service 20376f
{
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_diff *diff = NULL;
Packit Service 20376f
	diff_expects exp;
Packit Service 20376f
	char *pathspec = NULL;
Packit Service 20376f
	int use_iterator;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("status");
Packit Service 20376f
Packit Service 20376f
	opts.context_lines = 3;
Packit Service 20376f
	opts.interhunk_lines = 1;
Packit Service 20376f
	opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
Packit Service 20376f
	opts.pathspec.strings = &pathspec;
Packit Service 20376f
	opts.pathspec.count   = 1;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(13, exp.files);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
		cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	pathspec = "modified_file";
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(1, exp.files);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	pathspec = "subdir";
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(3, exp.files);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	pathspec = "*_deleted";
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(2, exp.files);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__to_index_with_pathlist_disabling_fnmatch(void)
Packit Service 20376f
{
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_diff *diff = NULL;
Packit Service 20376f
	diff_expects exp;
Packit Service 20376f
	char *pathspec = NULL;
Packit Service 20376f
	int use_iterator;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("status");
Packit Service 20376f
Packit Service 20376f
	opts.context_lines = 3;
Packit Service 20376f
	opts.interhunk_lines = 1;
Packit Service 20376f
	opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED |
Packit Service 20376f
		GIT_DIFF_DISABLE_PATHSPEC_MATCH;
Packit Service 20376f
	opts.pathspec.strings = &pathspec;
Packit Service 20376f
	opts.pathspec.count   = 0;
Packit Service 20376f
Packit Service 20376f
	/* ensure that an empty pathspec list is ignored */
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(13, exp.files);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
		cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* ensure that a single NULL pathspec is filtered out (like when using
Packit Service 20376f
	 * fnmatch filtering)
Packit Service 20376f
	 */
Packit Service 20376f
Packit Service 20376f
	opts.pathspec.count   = 1;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(13, exp.files);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
		cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	pathspec = "modified_file";
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(1, exp.files);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* ensure that subdirs can be specified */
Packit Service 20376f
	pathspec = "subdir";
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(3, exp.files);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* ensure that subdirs can be specified with a trailing slash */
Packit Service 20376f
	pathspec = "subdir/";
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(3, exp.files);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* ensure that fnmatching is completely disabled */
Packit Service 20376f
	pathspec = "subdir/*";
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(0, exp.files);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* ensure that the prefix matching isn't completely braindead */
Packit Service 20376f
	pathspec = "subdi";
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(0, exp.files);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* ensure that fnmatching isn't working at all */
Packit Service 20376f
	pathspec = "*_deleted";
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(0, exp.files);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__filemode_changes(void)
Packit Service 20376f
{
Packit Service 20376f
	git_diff *diff = NULL;
Packit Service 20376f
	diff_expects exp;
Packit Service 20376f
	int use_iterator;
Packit Service 20376f
Packit Service 20376f
	if (!cl_is_chmod_supported())
Packit Service 20376f
		return;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("issue_592");
Packit Service 20376f
Packit Service 20376f
	cl_repo_set_bool(g_repo, "core.filemode", true);
Packit Service 20376f
Packit Service 20376f
	/* test once with no mods */
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL));
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(
Packit Service 20376f
				diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(0, exp.files);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.hunks);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* chmod file and test again */
Packit Service 20376f
Packit Service 20376f
	cl_assert(cl_toggle_filemode("issue_592/a.txt"));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL));
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(
Packit Service 20376f
				diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(1, exp.files);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.hunks);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	cl_assert(cl_toggle_filemode("issue_592/a.txt"));
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__filemode_changes_with_filemode_false(void)
Packit Service 20376f
{
Packit Service 20376f
	git_diff *diff = NULL;
Packit Service 20376f
	diff_expects exp;
Packit Service 20376f
Packit Service 20376f
	if (!cl_is_chmod_supported())
Packit Service 20376f
		return;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("issue_592");
Packit Service 20376f
Packit Service 20376f
	cl_repo_set_bool(g_repo, "core.filemode", false);
Packit Service 20376f
Packit Service 20376f
	/* test once with no mods */
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL));
Packit Service 20376f
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
	cl_git_pass(git_diff_foreach(
Packit Service 20376f
		diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(0, exp.files);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
	cl_assert_equal_i(0, exp.hunks);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* chmod file and test again */
Packit Service 20376f
Packit Service 20376f
	cl_assert(cl_toggle_filemode("issue_592/a.txt"));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL));
Packit Service 20376f
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
	cl_git_pass(git_diff_foreach(diff, 
Packit Service 20376f
		diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(0, exp.files);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
	cl_assert_equal_i(0, exp.hunks);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	cl_assert(cl_toggle_filemode("issue_592/a.txt"));
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__head_index_and_workdir_all_differ(void)
Packit Service 20376f
{
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_diff *diff_i2t = NULL, *diff_w2i = NULL;
Packit Service 20376f
	diff_expects exp;
Packit Service 20376f
	char *pathspec = "staged_changes_modified_file";
Packit Service 20376f
	git_tree *tree;
Packit Service 20376f
	int use_iterator;
Packit Service 20376f
Packit Service 20376f
	/* For this file,
Packit Service 20376f
	 * - head->index diff has 1 line of context, 1 line of diff
Packit Service 20376f
	 * - index->workdir diff has 2 lines of context, 1 line of diff
Packit Service 20376f
	 * but
Packit Service 20376f
	 * - head->workdir diff has 1 line of context, 2 lines of diff
Packit Service 20376f
	 * Let's make sure the right one is returned from each fn.
Packit Service 20376f
	 */
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("status");
Packit Service 20376f
Packit Service 20376f
	tree = resolve_commit_oid_to_tree(g_repo, "26a125ee1bfc5df1e1b2e9441bbe63c8a7ae989f");
Packit Service 20376f
Packit Service 20376f
	opts.pathspec.strings = &pathspec;
Packit Service 20376f
	opts.pathspec.count   = 1;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_index(&diff_i2t, g_repo, tree, NULL, &opts));
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff_w2i, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff_i2t, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(
Packit Service 20376f
				diff_i2t, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(1, exp.files);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.hunks);
Packit Service 20376f
		cl_assert_equal_i(2, exp.lines);
Packit Service 20376f
		cl_assert_equal_i(1, exp.line_ctxt);
Packit Service 20376f
		cl_assert_equal_i(1, exp.line_adds);
Packit Service 20376f
		cl_assert_equal_i(0, exp.line_dels);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff_w2i, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(
Packit Service 20376f
				diff_w2i, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(1, exp.files);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.hunks);
Packit Service 20376f
		cl_assert_equal_i(3, exp.lines);
Packit Service 20376f
		cl_assert_equal_i(2, exp.line_ctxt);
Packit Service 20376f
		cl_assert_equal_i(1, exp.line_adds);
Packit Service 20376f
		cl_assert_equal_i(0, exp.line_dels);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_merge(diff_i2t, diff_w2i));
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff_i2t, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(
Packit Service 20376f
				diff_i2t, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(1, exp.files);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.hunks);
Packit Service 20376f
		cl_assert_equal_i(3, exp.lines);
Packit Service 20376f
		cl_assert_equal_i(1, exp.line_ctxt);
Packit Service 20376f
		cl_assert_equal_i(2, exp.line_adds);
Packit Service 20376f
		cl_assert_equal_i(0, exp.line_dels);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff_i2t);
Packit Service 20376f
	git_diff_free(diff_w2i);
Packit Service 20376f
Packit Service 20376f
	git_tree_free(tree);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__eof_newline_changes(void)
Packit Service 20376f
{
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_diff *diff = NULL;
Packit Service 20376f
	diff_expects exp;
Packit Service 20376f
	char *pathspec = "current_file";
Packit Service 20376f
	int use_iterator;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("status");
Packit Service 20376f
Packit Service 20376f
	opts.pathspec.strings = &pathspec;
Packit Service 20376f
	opts.pathspec.count   = 1;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(
Packit Service 20376f
				diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(0, exp.files);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.hunks);
Packit Service 20376f
		cl_assert_equal_i(0, exp.lines);
Packit Service 20376f
		cl_assert_equal_i(0, exp.line_ctxt);
Packit Service 20376f
		cl_assert_equal_i(0, exp.line_adds);
Packit Service 20376f
		cl_assert_equal_i(0, exp.line_dels);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	cl_git_append2file("status/current_file", "\n");
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(
Packit Service 20376f
				diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(1, exp.files);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.hunks);
Packit Service 20376f
		cl_assert_equal_i(2, exp.lines);
Packit Service 20376f
		cl_assert_equal_i(1, exp.line_ctxt);
Packit Service 20376f
		cl_assert_equal_i(1, exp.line_adds);
Packit Service 20376f
		cl_assert_equal_i(0, exp.line_dels);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	cl_git_rewritefile("status/current_file", "current_file");
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
Packit Service 20376f
		memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
		if (use_iterator)
Packit Service 20376f
			cl_git_pass(diff_foreach_via_iterator(
Packit Service 20376f
				diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
		else
Packit Service 20376f
			cl_git_pass(git_diff_foreach(
Packit Service 20376f
				diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_i(1, exp.files);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
		cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
		cl_assert_equal_i(1, exp.hunks);
Packit Service 20376f
		cl_assert_equal_i(3, exp.lines);
Packit Service 20376f
		cl_assert_equal_i(0, exp.line_ctxt);
Packit Service 20376f
		cl_assert_equal_i(1, exp.line_adds);
Packit Service 20376f
		cl_assert_equal_i(2, exp.line_dels);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* PREPARATION OF TEST DATA
Packit Service 20376f
 *
Packit Service 20376f
 * Since there is no command line equivalent of git_diff_tree_to_workdir,
Packit Service 20376f
 * it was a bit of a pain to confirm that I was getting the expected
Packit Service 20376f
 * results in the first part of this tests.  Here is what I ended up
Packit Service 20376f
 * doing to set my expectation for the file counts and results:
Packit Service 20376f
 *
Packit Service 20376f
 * Running "git ls-tree 26a125" and "git ls-tree aa27a6" shows:
Packit Service 20376f
 *
Packit Service 20376f
 *  A a0de7e0ac200c489c41c59dfa910154a70264e6e	current_file
Packit Service 20376f
 *  B 5452d32f1dd538eb0405e8a83cc185f79e25e80f	file_deleted
Packit Service 20376f
 *  C 452e4244b5d083ddf0460acf1ecc74db9dcfa11a	modified_file
Packit Service 20376f
 *  D 32504b727382542f9f089e24fddac5e78533e96c	staged_changes
Packit Service 20376f
 *  E 061d42a44cacde5726057b67558821d95db96f19	staged_changes_file_deleted
Packit Service 20376f
 *  F 70bd9443ada07063e7fbf0b3ff5c13f7494d89c2	staged_changes_modified_file
Packit Service 20376f
 *  G e9b9107f290627c04d097733a10055af941f6bca	staged_delete_file_deleted
Packit Service 20376f
 *  H dabc8af9bd6e9f5bbe96a176f1a24baf3d1f8916	staged_delete_modified_file
Packit Service 20376f
 *  I 53ace0d1cc1145a5f4fe4f78a186a60263190733	subdir/current_file
Packit Service 20376f
 *  J 1888c805345ba265b0ee9449b8877b6064592058	subdir/deleted_file
Packit Service 20376f
 *  K a6191982709b746d5650e93c2acf34ef74e11504	subdir/modified_file
Packit Service 20376f
 *  L e8ee89e15bbe9b20137715232387b3de5b28972e	subdir.txt
Packit Service 20376f
 *
Packit Service 20376f
 * --------
Packit Service 20376f
 *
Packit Service 20376f
 * find . ! -path ./.git/\* -a -type f | git hash-object --stdin-paths
Packit Service 20376f
 *
Packit Service 20376f
 *  A a0de7e0ac200c489c41c59dfa910154a70264e6e current_file
Packit Service 20376f
 *  M 6a79f808a9c6bc9531ac726c184bbcd9351ccf11 ignored_file
Packit Service 20376f
 *  C 0a539630525aca2e7bc84975958f92f10a64c9b6 modified_file
Packit Service 20376f
 *  N d4fa8600b4f37d7516bef4816ae2c64dbf029e3a new_file
Packit Service 20376f
 *  D 55d316c9ba708999f1918e9677d01dfcae69c6b9 staged_changes
Packit Service 20376f
 *  F 011c3440d5c596e21d836aa6d7b10eb581f68c49 staged_changes_modified_file
Packit Service 20376f
 *  H dabc8af9bd6e9f5bbe96a176f1a24baf3d1f8916 staged_delete_modified_file
Packit Service 20376f
 *  O 529a16e8e762d4acb7b9636ff540a00831f9155a staged_new_file
Packit Service 20376f
 *  P 8b090c06d14ffa09c4e880088ebad33893f921d1 staged_new_file_modified_file
Packit Service 20376f
 *  I 53ace0d1cc1145a5f4fe4f78a186a60263190733 subdir/current_file
Packit Service 20376f
 *  K 57274b75eeb5f36fd55527806d567b2240a20c57 subdir/modified_file
Packit Service 20376f
 *  Q 80a86a6931b91bc01c2dbf5ca55bdd24ad1ef466 subdir/new_file
Packit Service 20376f
 *  L e8ee89e15bbe9b20137715232387b3de5b28972e subdir.txt
Packit Service 20376f
 *
Packit Service 20376f
 * --------
Packit Service 20376f
 *
Packit Service 20376f
 *  A - current_file (UNMODIFIED) -> not in results
Packit Service 20376f
 *  B D file_deleted
Packit Service 20376f
 *  M I ignored_file (IGNORED)
Packit Service 20376f
 *  C M modified_file
Packit Service 20376f
 *  N U new_file (UNTRACKED)
Packit Service 20376f
 *  D M staged_changes
Packit Service 20376f
 *  E D staged_changes_file_deleted
Packit Service 20376f
 *  F M staged_changes_modified_file
Packit Service 20376f
 *  G D staged_delete_file_deleted
Packit Service 20376f
 *  H - staged_delete_modified_file (UNMODIFIED) -> not in results
Packit Service 20376f
 *  O U staged_new_file
Packit Service 20376f
 *  P U staged_new_file_modified_file
Packit Service 20376f
 *  I - subdir/current_file (UNMODIFIED) -> not in results
Packit Service 20376f
 *  J D subdir/deleted_file
Packit Service 20376f
 *  K M subdir/modified_file
Packit Service 20376f
 *  Q U subdir/new_file
Packit Service 20376f
 *  L - subdir.txt (UNMODIFIED) -> not in results
Packit Service 20376f
 *
Packit Service 20376f
 * Expect 13 files, 0 ADD, 4 DEL, 4 MOD, 1 IGN, 4 UNTR
Packit Service 20376f
 */
Packit Service 20376f
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__larger_hunks(void)
Packit Service 20376f
{
Packit Service 20376f
	const char *a_commit = "d70d245ed97ed2aa596dd1af6536e4bfdb047b69";
Packit Service 20376f
	const char *b_commit = "7a9e0b02e63179929fed24f0a3e0f19168114d10";
Packit Service 20376f
	git_tree *a, *b;
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	size_t i, d, num_d, h, num_h, l, num_l;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("diff");
Packit Service 20376f
Packit Service 20376f
	cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL);
Packit Service 20376f
	cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL);
Packit Service 20376f
Packit Service 20376f
	opts.context_lines = 1;
Packit Service 20376f
	opts.interhunk_lines = 0;
Packit Service 20376f
Packit Service 20376f
	for (i = 0; i <= 2; ++i) {
Packit Service 20376f
		git_diff *diff = NULL;
Packit Service 20376f
		git_patch *patch;
Packit Service 20376f
		const git_diff_hunk *hunk;
Packit Service 20376f
		const git_diff_line *line;
Packit Service 20376f
Packit Service 20376f
		/* okay, this is a bit silly, but oh well */
Packit Service 20376f
		switch (i) {
Packit Service 20376f
		case 0:
Packit Service 20376f
			cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
			break;
Packit Service 20376f
		case 1:
Packit Service 20376f
			cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, a, &opts));
Packit Service 20376f
			break;
Packit Service 20376f
		case 2:
Packit Service 20376f
			cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, b, &opts));
Packit Service 20376f
			break;
Packit Service 20376f
		}
Packit Service 20376f
Packit Service 20376f
		num_d = git_diff_num_deltas(diff);
Packit Service 20376f
		cl_assert_equal_i(2, (int)num_d);
Packit Service 20376f
Packit Service 20376f
		for (d = 0; d < num_d; ++d) {
Packit Service 20376f
			cl_git_pass(git_patch_from_diff(&patch, diff, d));
Packit Service 20376f
			cl_assert(patch);
Packit Service 20376f
Packit Service 20376f
			num_h = git_patch_num_hunks(patch);
Packit Service 20376f
			for (h = 0; h < num_h; h++) {
Packit Service 20376f
				cl_git_pass(git_patch_get_hunk(&hunk, &num_l, patch, h));
Packit Service 20376f
Packit Service 20376f
				for (l = 0; l < num_l; ++l) {
Packit Service 20376f
					cl_git_pass(
Packit Service 20376f
						git_patch_get_line_in_hunk(&line, patch, h, l));
Packit Service 20376f
					cl_assert(line);
Packit Service 20376f
				}
Packit Service 20376f
Packit Service 20376f
				/* confirm fail after the last item */
Packit Service 20376f
				cl_git_fail(
Packit Service 20376f
					git_patch_get_line_in_hunk(&line, patch, h, num_l));
Packit Service 20376f
			}
Packit Service 20376f
Packit Service 20376f
			/* confirm fail after the last item */
Packit Service 20376f
			cl_git_fail(git_patch_get_hunk(&hunk, &num_l, patch, num_h));
Packit Service 20376f
Packit Service 20376f
			git_patch_free(patch);
Packit Service 20376f
		}
Packit Service 20376f
Packit Service 20376f
		git_diff_free(diff);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_tree_free(a);
Packit Service 20376f
	git_tree_free(b);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Set up a test that exercises this code. The easiest test using existing
Packit Service 20376f
 * test data is probably to create a sandbox of submod2 and then run a
Packit Service 20376f
 * git_diff_tree_to_workdir against tree
Packit Service 20376f
 * 873585b94bdeabccea991ea5e3ec1a277895b698. As for what you should actually
Packit Service 20376f
 * test, you can start by just checking that the number of lines of diff
Packit Service 20376f
 * content matches the actual output of git diff. That will at least
Packit Service 20376f
 * demonstrate that the submodule content is being used to generate somewhat
Packit Service 20376f
 * comparable outputs. It is a test that would fail without this code and
Packit Service 20376f
 * will succeed with it.
Packit Service 20376f
 */
Packit Service 20376f
Packit Service 20376f
#include "../submodule/submodule_helpers.h"
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__submodules(void)
Packit Service 20376f
{
Packit Service 20376f
	const char *a_commit = "873585b94bdeabccea991ea5e3ec1a277895b698";
Packit Service 20376f
	git_tree *a;
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_diff *diff = NULL;
Packit Service 20376f
	diff_expects exp;
Packit Service 20376f
Packit Service 20376f
	g_repo = setup_fixture_submod2();
Packit Service 20376f
Packit Service 20376f
	a = resolve_commit_oid_to_tree(g_repo, a_commit);
Packit Service 20376f
Packit Service 20376f
	opts.flags =
Packit Service 20376f
		GIT_DIFF_INCLUDE_UNTRACKED |
Packit Service 20376f
		GIT_DIFF_INCLUDE_IGNORED |
Packit Service 20376f
		GIT_DIFF_RECURSE_UNTRACKED_DIRS |
Packit Service 20376f
		GIT_DIFF_SHOW_UNTRACKED_CONTENT;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, a, &opts));
Packit Service 20376f
Packit Service 20376f
	/* diff_print(stderr, diff); */
Packit Service 20376f
Packit Service 20376f
	/* essentially doing: git diff 873585b94bdeabccea991ea5e3ec1a277895b698 */
Packit Service 20376f
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_foreach(
Packit Service 20376f
		diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
	/* so "git diff 873585" returns:
Packit Service 20376f
	 *  M   .gitmodules
Packit Service 20376f
	 *  A   just_a_dir/contents
Packit Service 20376f
	 *  A   just_a_file
Packit Service 20376f
	 *  A   sm_added_and_uncommited
Packit Service 20376f
	 *  A   sm_changed_file
Packit Service 20376f
	 *  A   sm_changed_head
Packit Service 20376f
	 *  A   sm_changed_index
Packit Service 20376f
	 *  A   sm_changed_untracked_file
Packit Service 20376f
	 *  M   sm_missing_commits
Packit Service 20376f
	 *  A   sm_unchanged
Packit Service 20376f
	 * which is a little deceptive because of the difference between the
Packit Service 20376f
	 * "git diff <treeish>" results from "git_diff_tree_to_workdir".  The
Packit Service 20376f
	 * only significant difference is that those Added items will show up
Packit Service 20376f
	 * as Untracked items in the pure libgit2 diff.
Packit Service 20376f
	 *
Packit Service 20376f
	 * Then add in the two extra untracked items "not" and "not-submodule"
Packit Service 20376f
	 * to get the 12 files reported here.
Packit Service 20376f
	 */
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(12, exp.files);
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
	cl_assert_equal_i(2, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
	cl_assert_equal_i(10, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
Packit Service 20376f
	/* the following numbers match "git diff 873585" exactly */
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(9, exp.hunks);
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(33, exp.lines);
Packit Service 20376f
	cl_assert_equal_i(2, exp.line_ctxt);
Packit Service 20376f
	cl_assert_equal_i(30, exp.line_adds);
Packit Service 20376f
	cl_assert_equal_i(1, exp.line_dels);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
	git_tree_free(a);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__cannot_diff_against_a_bare_repository(void)
Packit Service 20376f
{
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_diff *diff = NULL;
Packit Service 20376f
	git_tree *tree;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("testrepo.git");
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(
Packit Service 20376f
		GIT_EBAREREPO, git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_repository_head_tree(&tree, g_repo));
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(
Packit Service 20376f
		GIT_EBAREREPO, git_diff_tree_to_workdir(&diff, g_repo, tree, &opts));
Packit Service 20376f
Packit Service 20376f
	git_tree_free(tree);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__to_null_tree(void)
Packit Service 20376f
{
Packit Service 20376f
	git_diff *diff;
Packit Service 20376f
	diff_expects exp;
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
Packit Service 20376f
	opts.flags = GIT_DIFF_INCLUDE_UNTRACKED |
Packit Service 20376f
		GIT_DIFF_RECURSE_UNTRACKED_DIRS;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("status");
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_foreach(
Packit Service 20376f
		diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(exp.files, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__checks_options_version(void)
Packit Service 20376f
{
Packit Service 20376f
	git_diff *diff;
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	const git_error *err;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("status");
Packit Service 20376f
Packit Service 20376f
	opts.version = 0;
Packit Service 20376f
	cl_git_fail(git_diff_tree_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
	err = giterr_last();
Packit Service 20376f
	cl_assert_equal_i(GITERR_INVALID, err->klass);
Packit Service 20376f
Packit Service 20376f
	giterr_clear();
Packit Service 20376f
	opts.version = 1024;
Packit Service 20376f
	cl_git_fail(git_diff_tree_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
	err = giterr_last();
Packit Service 20376f
	cl_assert_equal_i(GITERR_INVALID, err->klass);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__can_diff_empty_file(void)
Packit Service 20376f
{
Packit Service 20376f
	git_diff *diff;
Packit Service 20376f
	git_tree *tree;
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	struct stat st;
Packit Service 20376f
	git_patch *patch;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("attr_index");
Packit Service 20376f
Packit Service 20376f
	tree = resolve_commit_oid_to_tree(g_repo, "3812cfef3661"); /* HEAD */
Packit Service 20376f
Packit Service 20376f
	/* baseline - make sure there are no outstanding diffs */
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts));
Packit Service 20376f
	cl_assert_equal_i(2, (int)git_diff_num_deltas(diff));
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* empty contents of file */
Packit Service 20376f
Packit Service 20376f
	cl_git_rewritefile("attr_index/README.txt", "");
Packit Service 20376f
	cl_git_pass(git_path_lstat("attr_index/README.txt", &st);;
Packit Service 20376f
	cl_assert_equal_i(0, (int)st.st_size);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts));
Packit Service 20376f
	cl_assert_equal_i(3, (int)git_diff_num_deltas(diff));
Packit Service 20376f
	/* diffs are: .gitattributes, README.txt, sub/sub/.gitattributes */
Packit Service 20376f
	cl_git_pass(git_patch_from_diff(&patch, diff, 1));
Packit Service 20376f
	git_patch_free(patch);
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* remove a file altogether */
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(p_unlink("attr_index/README.txt"));
Packit Service 20376f
	cl_assert(!git_path_exists("attr_index/README.txt"));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts));
Packit Service 20376f
	cl_assert_equal_i(3, (int)git_diff_num_deltas(diff));
Packit Service 20376f
	cl_git_pass(git_patch_from_diff(&patch, diff, 1));
Packit Service 20376f
	git_patch_free(patch);
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	git_tree_free(tree);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__to_index_issue_1397(void)
Packit Service 20376f
{
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_diff *diff = NULL;
Packit Service 20376f
	diff_expects exp;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("issue_1397");
Packit Service 20376f
Packit Service 20376f
	cl_repo_set_bool(g_repo, "core.autocrlf", true);
Packit Service 20376f
Packit Service 20376f
	opts.context_lines = 3;
Packit Service 20376f
	opts.interhunk_lines = 1;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
	cl_git_pass(git_diff_foreach(
Packit Service 20376f
		diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(0, exp.files);
Packit Service 20376f
	cl_assert_equal_i(0, exp.hunks);
Packit Service 20376f
	cl_assert_equal_i(0, exp.lines);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
	diff = NULL;
Packit Service 20376f
Packit Service 20376f
	cl_git_rewritefile("issue_1397/crlf_file.txt",
Packit Service 20376f
		"first line\r\nsecond line modified\r\nboth with crlf");
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
	cl_git_pass(git_diff_foreach(
Packit Service 20376f
		diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(1, exp.files);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(1, exp.hunks);
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(5, exp.lines);
Packit Service 20376f
	cl_assert_equal_i(3, exp.line_ctxt);
Packit Service 20376f
	cl_assert_equal_i(1, exp.line_adds);
Packit Service 20376f
	cl_assert_equal_i(1, exp.line_dels);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__to_tree_issue_1397(void)
Packit Service 20376f
{
Packit Service 20376f
	const char *a_commit = "7f483a738"; /* the current HEAD */
Packit Service 20376f
	git_tree *a;
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_diff *diff = NULL;
Packit Service 20376f
	git_diff *diff2 = NULL;
Packit Service 20376f
	diff_expects exp;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("issue_1397");
Packit Service 20376f
Packit Service 20376f
	cl_repo_set_bool(g_repo, "core.autocrlf", true);
Packit Service 20376f
Packit Service 20376f
	a = resolve_commit_oid_to_tree(g_repo, a_commit);
Packit Service 20376f
Packit Service 20376f
	opts.context_lines = 3;
Packit Service 20376f
	opts.interhunk_lines = 1;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, a, &opts));
Packit Service 20376f
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
	cl_git_pass(git_diff_foreach(
Packit Service 20376f
		diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(0, exp.files);
Packit Service 20376f
	cl_assert_equal_i(0, exp.hunks);
Packit Service 20376f
	cl_assert_equal_i(0, exp.lines);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
	diff = NULL;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts));
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, NULL, &opts));
Packit Service 20376f
	cl_git_pass(git_diff_merge(diff, diff2));
Packit Service 20376f
	git_diff_free(diff2);
Packit Service 20376f
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
	cl_git_pass(git_diff_foreach(
Packit Service 20376f
		diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(0, exp.files);
Packit Service 20376f
	cl_assert_equal_i(0, exp.hunks);
Packit Service 20376f
	cl_assert_equal_i(0, exp.lines);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
	git_tree_free(a);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__untracked_directory_scenarios(void)
Packit Service 20376f
{
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_diff *diff = NULL;
Packit Service 20376f
	diff_expects exp;
Packit Service 20376f
	char *pathspec = NULL;
Packit Service 20376f
	static const char *files0[] = {
Packit Service 20376f
		"subdir/deleted_file",
Packit Service 20376f
		"subdir/modified_file",
Packit Service 20376f
		"subdir/new_file",
Packit Service 20376f
		NULL
Packit Service 20376f
	};
Packit Service 20376f
	static const char *files1[] = {
Packit Service 20376f
		"subdir/deleted_file",
Packit Service 20376f
		"subdir/directory/",
Packit Service 20376f
		"subdir/modified_file",
Packit Service 20376f
		"subdir/new_file",
Packit Service 20376f
		NULL
Packit Service 20376f
	};
Packit Service 20376f
	static const char *files2[] = {
Packit Service 20376f
		"subdir/deleted_file",
Packit Service 20376f
		"subdir/directory/more/notignored",
Packit Service 20376f
		"subdir/modified_file",
Packit Service 20376f
		"subdir/new_file",
Packit Service 20376f
		NULL
Packit Service 20376f
	};
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("status");
Packit Service 20376f
	cl_git_mkfile("status/.gitignore", "ignored\n");
Packit Service 20376f
Packit Service 20376f
	opts.context_lines = 3;
Packit Service 20376f
	opts.interhunk_lines = 1;
Packit Service 20376f
	opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
Packit Service 20376f
	opts.pathspec.strings = &pathspec;
Packit Service 20376f
	opts.pathspec.count   = 1;
Packit Service 20376f
	pathspec = "subdir";
Packit Service 20376f
Packit Service 20376f
	/* baseline for "subdir" pathspec */
Packit Service 20376f
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
	exp.names = files0;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(3, exp.files);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* empty directory */
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(p_mkdir("status/subdir/directory", 0777));
Packit Service 20376f
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
	exp.names = files1;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(4, exp.files);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* empty directory in empty directory */
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(p_mkdir("status/subdir/directory/empty", 0777));
Packit Service 20376f
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
	exp.names = files1;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(4, exp.files);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* directory with only ignored files */
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(p_mkdir("status/subdir/directory/deeper", 0777));
Packit Service 20376f
	cl_git_mkfile("status/subdir/directory/deeper/ignored", "ignore me\n");
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(p_mkdir("status/subdir/directory/another", 0777));
Packit Service 20376f
	cl_git_mkfile("status/subdir/directory/another/ignored", "ignore me\n");
Packit Service 20376f
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
	exp.names = files1;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(4, exp.files);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* directory with ignored directory (contents irrelevant) */
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(p_mkdir("status/subdir/directory/more", 0777));
Packit Service 20376f
	cl_git_pass(p_mkdir("status/subdir/directory/more/ignored", 0777));
Packit Service 20376f
	cl_git_mkfile("status/subdir/directory/more/ignored/notignored",
Packit Service 20376f
		"inside ignored dir\n");
Packit Service 20376f
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
	exp.names = files1;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(4, exp.files);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* quick version avoids directory scan */
Packit Service 20376f
Packit Service 20376f
	opts.flags = opts.flags | GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS;
Packit Service 20376f
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
	exp.names = files1;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(4, exp.files);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
	cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* directory with nested non-ignored content */
Packit Service 20376f
Packit Service 20376f
	opts.flags = opts.flags & ~GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS;
Packit Service 20376f
Packit Service 20376f
	cl_git_mkfile("status/subdir/directory/more/notignored",
Packit Service 20376f
		"not ignored deep under untracked\n");
Packit Service 20376f
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
	exp.names = files1;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(4, exp.files);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
	cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* use RECURSE_UNTRACKED_DIRS to get actual untracked files (no ignores) */
Packit Service 20376f
Packit Service 20376f
	opts.flags = opts.flags & ~GIT_DIFF_INCLUDE_IGNORED;
Packit Service 20376f
	opts.flags = opts.flags | GIT_DIFF_RECURSE_UNTRACKED_DIRS;
Packit Service 20376f
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
	exp.names = files2;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp);;
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(4, exp.files);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
	cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__untracked_directory_comes_last(void)
Packit Service 20376f
{
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_diff *diff = NULL;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("renames");
Packit Service 20376f
Packit Service 20376f
	cl_git_mkfile("renames/.gitignore", "*.ign\n");
Packit Service 20376f
	cl_git_pass(p_mkdir("renames/zzz_untracked", 0777));
Packit Service 20376f
	cl_git_mkfile("renames/zzz_untracked/an.ign", "ignore me please");
Packit Service 20376f
	cl_git_mkfile("renames/zzz_untracked/skip.ign", "ignore me really");
Packit Service 20376f
	cl_git_mkfile("renames/zzz_untracked/test.ign", "ignore me now");
Packit Service 20376f
Packit Service 20376f
	opts.context_lines = 3;
Packit Service 20376f
	opts.interhunk_lines = 1;
Packit Service 20376f
	opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	cl_assert(diff != NULL);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__untracked_with_bom(void)
Packit Service 20376f
{
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_diff *diff = NULL;
Packit Service 20376f
	const git_diff_delta *delta;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("empty_standard_repo");
Packit Service 20376f
	cl_repo_set_bool(g_repo, "core.autocrlf", true);
Packit Service 20376f
Packit Service 20376f
	cl_git_write2file("empty_standard_repo/bom.txt",
Packit Service 20376f
		"\xFF\xFE\x31\x00\x32\x00\x33\x00\x34\x00", 10, O_WRONLY|O_CREAT, 0664);
Packit Service 20376f
Packit Service 20376f
	opts.flags =
Packit Service 20376f
		GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_SHOW_UNTRACKED_CONTENT;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(1, git_diff_num_deltas(diff));
Packit Service 20376f
	cl_assert((delta = git_diff_get_delta(diff, 0)) != NULL);
Packit Service 20376f
	cl_assert_equal_i(GIT_DELTA_UNTRACKED, delta->status);
Packit Service 20376f
Packit Service 20376f
	/* not known at this point
Packit Service 20376f
	 * cl_assert((delta->flags & GIT_DIFF_FLAG_BINARY) != 0);
Packit Service 20376f
	 */
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__patience_diff(void)
Packit Service 20376f
{
Packit Service 20376f
	git_index *index;
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_diff *diff = NULL;
Packit Service 20376f
	git_patch *patch = NULL;
Packit Service 20376f
	git_buf buf = GIT_BUF_INIT;
Packit Service 20376f
	const char *expected_normal = "diff --git a/test.txt b/test.txt\nindex 34a5acc..d52725f 100644\n--- a/test.txt\n+++ b/test.txt\n@@ -1,10 +1,7 @@\n When I wrote this\n I did not know\n-how to create\n-a patience diff\n I did not know\n how to create\n+a patience diff\n another problem\n-I did not know\n-how to create\n a minimal diff\n";
Packit Service 20376f
	const char *expected_patience = "diff --git a/test.txt b/test.txt\nindex 34a5acc..d52725f 100644\n--- a/test.txt\n+++ b/test.txt\n@@ -1,10 +1,7 @@\n When I wrote this\n I did not know\n+I did not know\n how to create\n a patience diff\n-I did not know\n-how to create\n another problem\n-I did not know\n-how to create\n a minimal diff\n";
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("empty_standard_repo");
Packit Service 20376f
	cl_repo_set_bool(g_repo, "core.autocrlf", true);
Packit Service 20376f
	cl_git_pass(git_repository_index(&index, g_repo));
Packit Service 20376f
Packit Service 20376f
	cl_git_mkfile(
Packit Service 20376f
		"empty_standard_repo/test.txt",
Packit Service 20376f
		"When I wrote this\nI did not know\nhow to create\na patience diff\nI did not know\nhow to create\nanother problem\nI did not know\nhow to create\na minimal diff\n");
Packit Service 20376f
	cl_git_pass(git_index_add_bypath(index, "test.txt"));
Packit Service 20376f
	cl_repo_commit_from_index(NULL, g_repo, NULL, 1372350000, "Base");
Packit Service 20376f
	git_index_free(index);
Packit Service 20376f
Packit Service 20376f
	cl_git_rewritefile(
Packit Service 20376f
		"empty_standard_repo/test.txt",
Packit Service 20376f
		"When I wrote this\nI did not know\nI did not know\nhow to create\na patience diff\nanother problem\na minimal diff\n");
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
	cl_assert_equal_i(1, git_diff_num_deltas(diff));
Packit Service 20376f
	cl_git_pass(git_patch_from_diff(&patch, diff, 0));
Packit Service 20376f
	cl_git_pass(git_patch_to_buf(&buf, patch));
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_s(expected_normal, buf.ptr);
Packit Service 20376f
	git_buf_clear(&buf;;
Packit Service 20376f
	git_patch_free(patch);
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	opts.flags |= GIT_DIFF_PATIENCE;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
	cl_assert_equal_i(1, git_diff_num_deltas(diff));
Packit Service 20376f
	cl_git_pass(git_patch_from_diff(&patch, diff, 0));
Packit Service 20376f
	cl_git_pass(git_patch_to_buf(&buf, patch));
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_s(expected_patience, buf.ptr);
Packit Service 20376f
	git_buf_clear(&buf;;
Packit Service 20376f
Packit Service 20376f
	git_buf_free(&buf;;
Packit Service 20376f
	git_patch_free(patch);
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__with_stale_index(void)
Packit Service 20376f
{
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_diff *diff = NULL;
Packit Service 20376f
	git_index *idx = NULL;
Packit Service 20376f
	diff_expects exp;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("status");
Packit Service 20376f
	cl_git_pass(git_repository_index(&idx, g_repo));
Packit Service 20376f
Packit Service 20376f
	/* make the in-memory index invalid */
Packit Service 20376f
	{
Packit Service 20376f
		git_repository *r2;
Packit Service 20376f
		git_index *idx2;
Packit Service 20376f
		cl_git_pass(git_repository_open(&r2, "status"));
Packit Service 20376f
		cl_git_pass(git_repository_index(&idx2, r2));
Packit Service 20376f
		cl_git_pass(git_index_add_bypath(idx2, "new_file"));
Packit Service 20376f
		cl_git_pass(git_index_add_bypath(idx2, "subdir/new_file"));
Packit Service 20376f
		cl_git_pass(git_index_remove_bypath(idx2, "staged_new_file"));
Packit Service 20376f
		cl_git_pass(git_index_remove_bypath(idx2, "staged_changes_file_deleted"));
Packit Service 20376f
		cl_git_pass(git_index_write(idx2));
Packit Service 20376f
		git_index_free(idx2);
Packit Service 20376f
		git_repository_free(r2);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	opts.context_lines = 3;
Packit Service 20376f
	opts.interhunk_lines = 1;
Packit Service 20376f
	opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_INCLUDE_UNMODIFIED;
Packit Service 20376f
Packit Service 20376f
	/* first try with index pointer which should prevent reload */
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, idx, &opts));
Packit Service 20376f
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_foreach(
Packit Service 20376f
		diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(17, exp.files);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
	cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
	cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
	cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
	cl_assert_equal_i(5, exp.file_status[GIT_DELTA_UNMODIFIED]);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* now let's try without the index pointer which should trigger reload */
Packit Service 20376f
Packit Service 20376f
	/* two files that were UNTRACKED should have become UNMODIFIED */
Packit Service 20376f
	/* one file that was UNMODIFIED should now have become UNTRACKED */
Packit Service 20376f
	/* one file that was DELETED should now be gone completely */
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_foreach(
Packit Service 20376f
		diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(16, exp.files);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
	cl_assert_equal_i(3, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
	cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
	cl_assert_equal_i(3, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
	cl_assert_equal_i(6, exp.file_status[GIT_DELTA_UNMODIFIED]);
Packit Service 20376f
Packit Service 20376f
	git_index_free(idx);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static int touch_file(void *payload, git_buf *path)
Packit Service 20376f
{
Packit Service 20376f
	struct stat st;
Packit Service 20376f
	struct p_timeval times[2];
Packit Service 20376f
Packit Service 20376f
	GIT_UNUSED(payload);
Packit Service 20376f
	if (git_path_isdir(path->ptr))
Packit Service 20376f
		return 0;
Packit Service 20376f
Packit Service 20376f
	cl_must_pass(p_stat(path->ptr, &st);;
Packit Service 20376f
Packit Service 20376f
	times[0].tv_sec = st.st_mtime + 3;
Packit Service 20376f
	times[0].tv_usec = 0;
Packit Service 20376f
	times[1].tv_sec = st.st_mtime + 3;
Packit Service 20376f
	times[1].tv_usec = 0;
Packit Service 20376f
Packit Service 20376f
	cl_must_pass(p_utimes(path->ptr, times));
Packit Service 20376f
	return 0;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static void basic_diff_status(git_diff **out, const git_diff_options *opts)
Packit Service 20376f
{
Packit Service 20376f
	diff_expects exp;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(out, g_repo, NULL, opts));
Packit Service 20376f
Packit Service 20376f
	memset(&exp, 0, sizeof(exp));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_foreach(
Packit Service 20376f
		*out, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(13, exp.files);
Packit Service 20376f
	cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
Packit Service 20376f
	cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]);
Packit Service 20376f
	cl_assert_equal_i(4, exp.file_status[GIT_DELTA_MODIFIED]);
Packit Service 20376f
	cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]);
Packit Service 20376f
	cl_assert_equal_i(4, exp.file_status[GIT_DELTA_UNTRACKED]);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__can_update_index(void)
Packit Service 20376f
{
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_diff *diff = NULL;
Packit Service 20376f
	git_diff_perfdata perf = GIT_DIFF_PERFDATA_INIT;
Packit Service 20376f
	git_index *index;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("status");
Packit Service 20376f
Packit Service 20376f
	/* touch all the files so stat times are different */
Packit Service 20376f
	{
Packit Service 20376f
		git_buf path = GIT_BUF_INIT;
Packit Service 20376f
		cl_git_pass(git_buf_sets(&path, "status"));
Packit Service 20376f
		cl_git_pass(git_path_direach(&path, 0, touch_file, NULL));
Packit Service 20376f
		git_buf_free(&path);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
Packit Service 20376f
Packit Service 20376f
	basic_diff_status(&diff, &opts);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_get_perfdata(&perf, diff));
Packit Service 20376f
	cl_assert_equal_sz(13 + 3, perf.stat_calls);
Packit Service 20376f
	cl_assert_equal_sz(5, perf.oid_calculations);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* now allow diff to update stat cache */
Packit Service 20376f
	opts.flags |= GIT_DIFF_UPDATE_INDEX;
Packit Service 20376f
Packit Service 20376f
	/* advance a tick for the index so we don't re-calculate racily-clean entries */
Packit Service 20376f
	cl_git_pass(git_repository_index__weakptr(&index, g_repo));
Packit Service 20376f
	tick_index(index);
Packit Service 20376f
Packit Service 20376f
	basic_diff_status(&diff, &opts);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_get_perfdata(&perf, diff));
Packit Service 20376f
	cl_assert_equal_sz(13 + 3, perf.stat_calls);
Packit Service 20376f
	cl_assert_equal_sz(5, perf.oid_calculations);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* now if we do it again, we should see fewer OID calculations */
Packit Service 20376f
Packit Service 20376f
	/* tick again as the index updating from the previous diff might have reset the timestamp */
Packit Service 20376f
	tick_index(index);
Packit Service 20376f
	basic_diff_status(&diff, &opts);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_get_perfdata(&perf, diff));
Packit Service 20376f
	cl_assert_equal_sz(13 + 3, perf.stat_calls);
Packit Service 20376f
	cl_assert_equal_sz(0, perf.oid_calculations);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
#define STR7    "0123456"
Packit Service 20376f
#define STR8    "01234567"
Packit Service 20376f
#define STR40   STR8   STR8   STR8   STR8   STR8
Packit Service 20376f
#define STR200  STR40  STR40  STR40  STR40  STR40
Packit Service 20376f
#define STR999Z STR200 STR200 STR200 STR200 STR40 STR40 STR40 STR40 \
Packit Service 20376f
	            STR8 STR8 STR8 STR8 STR7 "\0"
Packit Service 20376f
#define STR1000 STR200 STR200 STR200 STR200 STR200
Packit Service 20376f
#define STR3999Z STR1000 STR1000 STR1000 STR999Z
Packit Service 20376f
#define STR4000 STR1000 STR1000 STR1000 STR1000
Packit Service 20376f
Packit Service 20376f
static void assert_delta_binary(git_diff *diff, size_t idx, int is_binary)
Packit Service 20376f
{
Packit Service 20376f
	git_patch *patch;
Packit Service 20376f
	const git_diff_delta *delta;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_patch_from_diff(&patch, diff, idx));
Packit Service 20376f
	delta = git_patch_get_delta(patch);
Packit Service 20376f
	cl_assert_equal_b((delta->flags & GIT_DIFF_FLAG_BINARY), is_binary);
Packit Service 20376f
	git_patch_free(patch);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__binary_detection(void)
Packit Service 20376f
{
Packit Service 20376f
	git_index *idx;
Packit Service 20376f
	git_diff *diff = NULL;
Packit Service 20376f
	git_buf b = GIT_BUF_INIT;
Packit Service 20376f
	int i;
Packit Service 20376f
	git_buf data[10] = {
Packit Service 20376f
		{ "1234567890", 0, 0 },         /* 0 - all ascii text control */
Packit Service 20376f
		{ "\xC3\x85\xC3\xBC\xE2\x80\xA0\x48\xC3\xB8\xCF\x80\xCE\xA9", 0, 0 },            /* 1 - UTF-8 multibyte text */
Packit Service 20376f
		{ "\xEF\xBB\xBF\xC3\x9C\xE2\xA4\x92\xC6\x92\x38\xC2\xA3\xE2\x82\xAC", 0, 0 }, /* 2 - UTF-8 with BOM */
Packit Service 20376f
		{ STR999Z, 0, 1000 },           /* 3 - ASCII with NUL at 1000 */
Packit Service 20376f
		{ STR3999Z, 0, 4000 },          /* 4 - ASCII with NUL at 4000 */
Packit Service 20376f
		{ STR4000 STR3999Z "x", 0, 8001 }, /* 5 - ASCII with NUL at 8000 */
Packit Service 20376f
		{ STR4000 STR4000 "\0", 0, 8001 }, /* 6 - ASCII with NUL at 8001 */
Packit Service 20376f
		{ "\x00\xDC\x00\x6E\x21\x39\xFE\x0E\x00\x63\x00\xF8"
Packit Service 20376f
		  "\x00\x64\x00\x65\x20\x48", 0, 18 }, /* 7 - UTF-16 text */
Packit Service 20376f
		{ "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d"
Packit Service 20376f
		  "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d",
Packit Service 20376f
		  0, 26 }, /* 8 - All non-printable characters (no NUL) */
Packit Service 20376f
		{ "Hello \x01\x02\x03\x04\x05\x06 World!\x01\x02\x03\x04"
Packit Service 20376f
		  "\x05\x06\x07", 0, 26 }, /* 9 - 50-50 non-printable (no NUL) */
Packit Service 20376f
	};
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("empty_standard_repo");
Packit Service 20376f
	cl_git_pass(git_repository_index(&idx, g_repo));
Packit Service 20376f
Packit Service 20376f
	/* We start with ASCII in index and test data in workdir,
Packit Service 20376f
	 * then we will try with test data in index and ASCII in workdir.
Packit Service 20376f
	 */
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_buf_sets(&b, "empty_standard_repo/0"));
Packit Service 20376f
	for (i = 0; i < 10; ++i) {
Packit Service 20376f
		b.ptr[b.size - 1] = '0' + i;
Packit Service 20376f
		cl_git_mkfile(b.ptr, "baseline");
Packit Service 20376f
		cl_git_pass(git_index_add_bypath(idx, &b.ptr[b.size - 1]));
Packit Service 20376f
Packit Service 20376f
		if (data[i].size == 0)
Packit Service 20376f
			data[i].size = strlen(data[i].ptr);
Packit Service 20376f
		cl_git_write2file(
Packit Service 20376f
			b.ptr, data[i].ptr, data[i].size, O_WRONLY|O_TRUNC, 0664);
Packit Service 20376f
	}
Packit Service 20376f
	git_index_write(idx);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL));
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(10, git_diff_num_deltas(diff));
Packit Service 20376f
Packit Service 20376f
	/* using diff binary detection (i.e. looking for NUL byte) */
Packit Service 20376f
	assert_delta_binary(diff, 0, false);
Packit Service 20376f
	assert_delta_binary(diff, 1, false);
Packit Service 20376f
	assert_delta_binary(diff, 2, false);
Packit Service 20376f
	assert_delta_binary(diff, 3, true);
Packit Service 20376f
	assert_delta_binary(diff, 4, true);
Packit Service 20376f
	assert_delta_binary(diff, 5, true);
Packit Service 20376f
	assert_delta_binary(diff, 6, false);
Packit Service 20376f
	assert_delta_binary(diff, 7, true);
Packit Service 20376f
	assert_delta_binary(diff, 8, false);
Packit Service 20376f
	assert_delta_binary(diff, 9, false);
Packit Service 20376f
	/* The above have been checked to match command-line Git */
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_buf_sets(&b, "empty_standard_repo/0"));
Packit Service 20376f
	for (i = 0; i < 10; ++i) {
Packit Service 20376f
		b.ptr[b.size - 1] = '0' + i;
Packit Service 20376f
		cl_git_pass(git_index_add_bypath(idx, &b.ptr[b.size - 1]));
Packit Service 20376f
Packit Service 20376f
		cl_git_write2file(b.ptr, "baseline\n", 9, O_WRONLY|O_TRUNC, 0664);
Packit Service 20376f
	}
Packit Service 20376f
	git_index_write(idx);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL));
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(10, git_diff_num_deltas(diff));
Packit Service 20376f
Packit Service 20376f
	/* using diff binary detection (i.e. looking for NUL byte) */
Packit Service 20376f
	assert_delta_binary(diff, 0, false);
Packit Service 20376f
	assert_delta_binary(diff, 1, false);
Packit Service 20376f
	assert_delta_binary(diff, 2, false);
Packit Service 20376f
	assert_delta_binary(diff, 3, true);
Packit Service 20376f
	assert_delta_binary(diff, 4, true);
Packit Service 20376f
	assert_delta_binary(diff, 5, true);
Packit Service 20376f
	assert_delta_binary(diff, 6, false);
Packit Service 20376f
	assert_delta_binary(diff, 7, true);
Packit Service 20376f
	assert_delta_binary(diff, 8, false);
Packit Service 20376f
	assert_delta_binary(diff, 9, false);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	git_index_free(idx);
Packit Service 20376f
	git_buf_free(&b);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__to_index_conflicted(void) {
Packit Service 20376f
	const char *a_commit = "26a125ee1bf"; /* the current HEAD */
Packit Service 20376f
	git_index_entry ancestor = {{0}}, ours = {{0}}, theirs = {{0}};
Packit Service 20376f
	git_tree *a;
Packit Service 20376f
	git_index *index;
Packit Service 20376f
	git_diff *diff1, *diff2;
Packit Service 20376f
	const git_diff_delta *delta;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("status");
Packit Service 20376f
	a = resolve_commit_oid_to_tree(g_repo, a_commit);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_repository_index(&index, g_repo));
Packit Service 20376f
Packit Service 20376f
	ancestor.path = ours.path = theirs.path = "_file";
Packit Service 20376f
	ancestor.mode = ours.mode = theirs.mode = 0100644;
Packit Service 20376f
	git_oid_fromstr(&ancestor.id, "d427e0b2e138501a3d15cc376077a3631e15bd46");
Packit Service 20376f
	git_oid_fromstr(&ours.id, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf");
Packit Service 20376f
	git_oid_fromstr(&theirs.id, "2bd0a343aeef7a2cf0d158478966a6e587ff3863");
Packit Service 20376f
	cl_git_pass(git_index_conflict_add(index, &ancestor, &ours, &theirs));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_index(&diff1, g_repo, a, index, NULL));
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, index, NULL));
Packit Service 20376f
	cl_git_pass(git_diff_merge(diff1, diff2));
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(git_diff_num_deltas(diff1), 12);
Packit Service 20376f
	delta = git_diff_get_delta(diff1, 0);
Packit Service 20376f
	cl_assert_equal_s(delta->old_file.path, "_file");
Packit Service 20376f
	cl_assert_equal_i(delta->nfiles, 1);
Packit Service 20376f
	cl_assert_equal_i(delta->status, GIT_DELTA_CONFLICTED);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff2);
Packit Service 20376f
	git_diff_free(diff1);
Packit Service 20376f
	git_index_free(index);
Packit Service 20376f
	git_tree_free(a);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__only_writes_index_when_necessary(void)
Packit Service 20376f
{
Packit Service 20376f
	git_index *index;
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_diff *diff = NULL;
Packit Service 20376f
	git_reference *head;
Packit Service 20376f
	git_object *head_object;
Packit Service 20376f
	git_oid initial, first, second;
Packit Service 20376f
	git_buf path = GIT_BUF_INIT;
Packit Service 20376f
	struct stat st;
Packit Service 20376f
	struct p_timeval times[2];
Packit Service 20376f
Packit Service 20376f
	opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_UPDATE_INDEX;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("status");
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_repository_index(&index, g_repo));
Packit Service 20376f
	cl_git_pass(git_repository_head(&head, g_repo));
Packit Service 20376f
	cl_git_pass(git_reference_peel(&head_object, head, GIT_OBJ_COMMIT));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_reset(g_repo, head_object, GIT_RESET_HARD, NULL));
Packit Service 20376f
Packit Service 20376f
	git_oid_cpy(&initial, git_index_checksum(index));
Packit Service 20376f
Packit Service 20376f
	/* update the index timestamp to avoid raciness */
Packit Service 20376f
	cl_must_pass(p_stat("status/.git/index", &st);;
Packit Service 20376f
Packit Service 20376f
	times[0].tv_sec = st.st_mtime + 5;
Packit Service 20376f
	times[0].tv_usec = 0;
Packit Service 20376f
	times[1].tv_sec = st.st_mtime + 5;
Packit Service 20376f
	times[1].tv_usec = 0;
Packit Service 20376f
Packit Service 20376f
	cl_must_pass(p_utimes("status/.git/index", times));
Packit Service 20376f
Packit Service 20376f
	/* ensure diff doesn't touch the index */
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	git_oid_cpy(&first, git_index_checksum(index));
Packit Service 20376f
	cl_assert(!git_oid_equal(&initial, &first));
Packit Service 20376f
Packit Service 20376f
	/* touch all the files so stat times are different */
Packit Service 20376f
	cl_git_pass(git_buf_sets(&path, "status"));
Packit Service 20376f
	cl_git_pass(git_path_direach(&path, 0, touch_file, NULL));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* ensure the second diff did update the index */
Packit Service 20376f
	git_oid_cpy(&second, git_index_checksum(index));
Packit Service 20376f
	cl_assert(!git_oid_equal(&first, &second));
Packit Service 20376f
Packit Service 20376f
	git_buf_free(&path);
Packit Service 20376f
	git_object_free(head_object);
Packit Service 20376f
	git_reference_free(head);
Packit Service 20376f
	git_index_free(index);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__to_index_pathlist(void)
Packit Service 20376f
{
Packit Service 20376f
	git_index *index;
Packit Service 20376f
	git_diff *diff;
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_vector pathlist = GIT_VECTOR_INIT;
Packit Service 20376f
Packit Service 20376f
	git_vector_insert(&pathlist, "foobar/asdf");
Packit Service 20376f
	git_vector_insert(&pathlist, "subdir/asdf");
Packit Service 20376f
	git_vector_insert(&pathlist, "ignored/asdf");
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("status");
Packit Service 20376f
Packit Service 20376f
	cl_git_mkfile("status/.gitignore", ".gitignore\n" "ignored/\n");
Packit Service 20376f
Packit Service 20376f
	cl_must_pass(p_mkdir("status/foobar", 0777));
Packit Service 20376f
	cl_git_mkfile("status/foobar/one", "one\n");
Packit Service 20376f
Packit Service 20376f
	cl_must_pass(p_mkdir("status/ignored", 0777));
Packit Service 20376f
	cl_git_mkfile("status/ignored/one", "one\n");
Packit Service 20376f
	cl_git_mkfile("status/ignored/two", "two\n");
Packit Service 20376f
	cl_git_mkfile("status/ignored/three", "three\n");
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_repository_index(&index, g_repo));
Packit Service 20376f
Packit Service 20376f
	opts.flags = GIT_DIFF_INCLUDE_IGNORED;
Packit Service 20376f
	opts.pathspec.strings = (char **)pathlist.contents;
Packit Service 20376f
	opts.pathspec.count = pathlist.length;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, &opts));
Packit Service 20376f
	cl_assert_equal_i(0, git_diff_num_deltas(diff));
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	opts.flags |= GIT_DIFF_DISABLE_PATHSPEC_MATCH;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, &opts));
Packit Service 20376f
	cl_assert_equal_i(0, git_diff_num_deltas(diff));
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	git_index_free(index);
Packit Service 20376f
	git_vector_free(&pathlist);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_workdir__symlink_changed_on_non_symlink_platform(void)
Packit Service 20376f
{
Packit Service 20376f
	git_tree *tree;
Packit Service 20376f
	git_diff *diff;
Packit Service 20376f
	diff_expects exp = {0};
Packit Service 20376f
	const git_diff_delta *delta;
Packit Service 20376f
	const char *commit = "7fccd7";
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_vector pathlist = GIT_VECTOR_INIT;
Packit Service 20376f
	int symlinks;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("unsymlinked.git");
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_repository__cvar(&symlinks, g_repo, GIT_CVAR_SYMLINKS));
Packit Service 20376f
Packit Service 20376f
	if (symlinks)
Packit Service 20376f
		cl_skip();
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_vector_insert(&pathlist, "include/Nu/Nu.h"));
Packit Service 20376f
Packit Service 20376f
	opts.pathspec.strings = (char **)pathlist.contents;
Packit Service 20376f
	opts.pathspec.count = pathlist.length;
Packit Service 20376f
Packit Service 20376f
	cl_must_pass(p_mkdir("symlink", 0777));
Packit Service 20376f
	cl_git_pass(git_repository_set_workdir(g_repo, "symlink", false));
Packit Service 20376f
Packit Service 20376f
	cl_assert((tree = resolve_commit_oid_to_tree(g_repo, commit)) != NULL);
Packit Service 20376f
Packit Service 20376f
	/* first, do the diff with the original contents */
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_futils_mkpath2file("symlink/include/Nu/Nu.h", 0755));
Packit Service 20376f
	cl_git_mkfile("symlink/include/Nu/Nu.h", "../../objc/Nu.h");
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts));
Packit Service 20376f
	cl_assert_equal_i(0, git_diff_num_deltas(diff));
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* now update the contents and expect a difference, but that the file
Packit Service 20376f
	 * mode has persisted as a symbolic link.
Packit Service 20376f
	 */
Packit Service 20376f
Packit Service 20376f
	cl_git_rewritefile("symlink/include/Nu/Nu.h", "awesome content\n");
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_foreach(
Packit Service 20376f
		diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp);;
Packit Service 20376f
	cl_assert_equal_i(1, exp.files);
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(1, git_diff_num_deltas(diff));
Packit Service 20376f
	delta = git_diff_get_delta(diff, 0);
Packit Service 20376f
	cl_assert_equal_i(GIT_FILEMODE_LINK, delta->old_file.mode);
Packit Service 20376f
	cl_assert_equal_i(GIT_FILEMODE_LINK, delta->new_file.mode);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_futils_rmdir_r("symlink", NULL, GIT_RMDIR_REMOVE_FILES));
Packit Service 20376f
Packit Service 20376f
	git_tree_free(tree);
Packit Service 20376f
	git_vector_free(&pathlist);
Packit Service 20376f
}