Blame tests/diff/patch.c

Packit Service 20376f
#include "clar_libgit2.h"
Packit Service 20376f
#include "git2/sys/repository.h"
Packit Service 20376f
Packit Service 20376f
#include "diff_helpers.h"
Packit Service 20376f
#include "diff.h"
Packit Service 20376f
#include "repository.h"
Packit Service 20376f
#include "buf_text.h"
Packit Service 20376f
Packit Service 20376f
static git_repository *g_repo = NULL;
Packit Service 20376f
Packit Service 20376f
void test_diff_patch__initialize(void)
Packit Service 20376f
{
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_patch__cleanup(void)
Packit Service 20376f
{
Packit Service 20376f
	cl_git_sandbox_cleanup();
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
#define EXPECTED_HEADER "diff --git a/subdir.txt b/subdir.txt\n" \
Packit Service 20376f
	"deleted file mode 100644\n" \
Packit Service 20376f
	"index e8ee89e..0000000\n" \
Packit Service 20376f
	"--- a/subdir.txt\n" \
Packit Service 20376f
	"+++ /dev/null\n"
Packit Service 20376f
Packit Service 20376f
#define EXPECTED_HUNK "@@ -1,2 +0,0 @@\n"
Packit Service 20376f
Packit Service 20376f
static int check_removal_cb(
Packit Service 20376f
	const git_diff_delta *delta,
Packit Service 20376f
	const git_diff_hunk *hunk,
Packit Service 20376f
	const git_diff_line *line,
Packit Service 20376f
	void *payload)
Packit Service 20376f
{
Packit Service 20376f
	switch (line->origin) {
Packit Service 20376f
	case GIT_DIFF_LINE_FILE_HDR:
Packit Service 20376f
		cl_assert_equal_s(EXPECTED_HEADER, line->content);
Packit Service 20376f
		cl_assert(hunk == NULL);
Packit Service 20376f
		goto check_delta;
Packit Service 20376f
Packit Service 20376f
	case GIT_DIFF_LINE_HUNK_HDR:
Packit Service 20376f
		cl_assert_equal_s(EXPECTED_HUNK, line->content);
Packit Service 20376f
		goto check_hunk;
Packit Service 20376f
Packit Service 20376f
	case GIT_DIFF_LINE_CONTEXT:
Packit Service 20376f
	case GIT_DIFF_LINE_DELETION:
Packit Service 20376f
		if (payload != NULL)
Packit Service 20376f
			return *(int *)payload;
Packit Service 20376f
		goto check_hunk;
Packit Service 20376f
Packit Service 20376f
	default:
Packit Service 20376f
		/* unexpected code path */
Packit Service 20376f
		return -1;
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
check_hunk:
Packit Service 20376f
	cl_assert(hunk != NULL);
Packit Service 20376f
	cl_assert_equal_i(1, hunk->old_start);
Packit Service 20376f
	cl_assert_equal_i(2, hunk->old_lines);
Packit Service 20376f
	cl_assert_equal_i(0, hunk->new_start);
Packit Service 20376f
	cl_assert_equal_i(0, hunk->new_lines);
Packit Service 20376f
Packit Service 20376f
check_delta:
Packit Service 20376f
	cl_assert_equal_s("subdir.txt", delta->old_file.path);
Packit Service 20376f
	cl_assert_equal_s("subdir.txt", delta->new_file.path);
Packit Service 20376f
	cl_assert_equal_i(GIT_DELTA_DELETED, delta->status);
Packit Service 20376f
Packit Service 20376f
	return 0;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_patch__can_properly_display_the_removal_of_a_file(void)
Packit Service 20376f
{
Packit Service 20376f
	/*
Packit Service 20376f
	* $ git diff 26a125e..735b6a2
Packit Service 20376f
	* diff --git a/subdir.txt b/subdir.txt
Packit Service 20376f
	* deleted file mode 100644
Packit Service 20376f
	* index e8ee89e..0000000
Packit Service 20376f
	* --- a/subdir.txt
Packit Service 20376f
	* +++ /dev/null
Packit Service 20376f
	* @@ -1,2 +0,0 @@
Packit Service 20376f
	* -Is it a bird?
Packit Service 20376f
	* -Is it a plane?
Packit Service 20376f
	*/
Packit Service 20376f
Packit Service 20376f
	const char *one_sha = "26a125e";
Packit Service 20376f
	const char *another_sha = "735b6a2";
Packit Service 20376f
	git_tree *one, *another;
Packit Service 20376f
	git_diff *diff;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("status");
Packit Service 20376f
Packit Service 20376f
	one = resolve_commit_oid_to_tree(g_repo, one_sha);
Packit Service 20376f
	another = resolve_commit_oid_to_tree(g_repo, another_sha);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, one, another, NULL));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_print(
Packit Service 20376f
		diff, GIT_DIFF_FORMAT_PATCH, check_removal_cb, NULL));
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	git_tree_free(another);
Packit Service 20376f
	git_tree_free(one);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_patch__can_cancel_diff_print(void)
Packit Service 20376f
{
Packit Service 20376f
	const char *one_sha = "26a125e";
Packit Service 20376f
	const char *another_sha = "735b6a2";
Packit Service 20376f
	git_tree *one, *another;
Packit Service 20376f
	git_diff *diff;
Packit Service 20376f
	int fail_with;
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("status");
Packit Service 20376f
Packit Service 20376f
	one = resolve_commit_oid_to_tree(g_repo, one_sha);
Packit Service 20376f
	another = resolve_commit_oid_to_tree(g_repo, another_sha);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, one, another, NULL));
Packit Service 20376f
Packit Service 20376f
	fail_with = -2323;
Packit Service 20376f
Packit Service 20376f
	cl_git_fail_with(git_diff_print(
Packit Service 20376f
		diff, GIT_DIFF_FORMAT_PATCH, check_removal_cb, &fail_with),
Packit Service 20376f
		fail_with);
Packit Service 20376f
Packit Service 20376f
	fail_with = 45;
Packit Service 20376f
Packit Service 20376f
	cl_git_fail_with(git_diff_print(
Packit Service 20376f
		diff, GIT_DIFF_FORMAT_PATCH, check_removal_cb, &fail_with),
Packit Service 20376f
		fail_with);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	git_tree_free(another);
Packit Service 20376f
	git_tree_free(one);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_patch__to_string(void)
Packit Service 20376f
{
Packit Service 20376f
	const char *one_sha = "26a125e";
Packit Service 20376f
	const char *another_sha = "735b6a2";
Packit Service 20376f
	git_tree *one, *another;
Packit Service 20376f
	git_diff *diff;
Packit Service 20376f
	git_patch *patch;
Packit Service 20376f
	git_buf buf = GIT_BUF_INIT;
Packit Service 20376f
	const char *expected = "diff --git a/subdir.txt b/subdir.txt\ndeleted file mode 100644\nindex e8ee89e..0000000\n--- a/subdir.txt\n+++ /dev/null\n@@ -1,2 +0,0 @@\n-Is it a bird?\n-Is it a plane?\n";
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("status");
Packit Service 20376f
Packit Service 20376f
	one = resolve_commit_oid_to_tree(g_repo, one_sha);
Packit Service 20376f
	another = resolve_commit_oid_to_tree(g_repo, another_sha);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, one, another, NULL));
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_patch_from_diff(&patch, diff, 0));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_patch_to_buf(&buf, patch));
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_s(expected, buf.ptr);
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_sz(31, git_patch_size(patch, 0, 0, 0));
Packit Service 20376f
	cl_assert_equal_sz(31, git_patch_size(patch, 1, 0, 0));
Packit Service 20376f
	cl_assert_equal_sz(31 + 16, git_patch_size(patch, 1, 1, 0));
Packit Service 20376f
	cl_assert_equal_sz(strlen(expected), git_patch_size(patch, 1, 1, 1));
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
	git_tree_free(another);
Packit Service 20376f
	git_tree_free(one);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_patch__config_options(void)
Packit Service 20376f
{
Packit Service 20376f
	const char *one_sha = "26a125e"; /* current HEAD */
Packit Service 20376f
	git_tree *one;
Packit Service 20376f
	git_config *cfg;
Packit Service 20376f
	git_diff *diff;
Packit Service 20376f
	git_patch *patch;
Packit Service 20376f
	git_buf buf = GIT_BUF_INIT;
Packit Service 20376f
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	char *onefile = "staged_changes_modified_file";
Packit Service 20376f
	const char *expected1 = "diff --git c/staged_changes_modified_file i/staged_changes_modified_file\nindex 70bd944..906ee77 100644\n--- c/staged_changes_modified_file\n+++ i/staged_changes_modified_file\n@@ -1 +1,2 @@\n staged_changes_modified_file\n+staged_changes_modified_file\n";
Packit Service 20376f
	const char *expected2 = "diff --git i/staged_changes_modified_file w/staged_changes_modified_file\nindex 906ee77..011c344 100644\n--- i/staged_changes_modified_file\n+++ w/staged_changes_modified_file\n@@ -1,2 +1,3 @@\n staged_changes_modified_file\n staged_changes_modified_file\n+staged_changes_modified_file\n";
Packit Service 20376f
	const char *expected3 = "diff --git staged_changes_modified_file staged_changes_modified_file\nindex 906ee77..011c344 100644\n--- staged_changes_modified_file\n+++ staged_changes_modified_file\n@@ -1,2 +1,3 @@\n staged_changes_modified_file\n staged_changes_modified_file\n+staged_changes_modified_file\n";
Packit Service 20376f
	const char *expected4 = "diff --git staged_changes_modified_file staged_changes_modified_file\nindex 70bd9443ada0..906ee7711f4f 100644\n--- staged_changes_modified_file\n+++ staged_changes_modified_file\n@@ -1 +1,2 @@\n staged_changes_modified_file\n+staged_changes_modified_file\n";
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("status");
Packit Service 20376f
	cl_git_pass(git_repository_config(&cfg, g_repo));
Packit Service 20376f
	one = resolve_commit_oid_to_tree(g_repo, one_sha);
Packit Service 20376f
	opts.pathspec.count = 1;
Packit Service 20376f
	opts.pathspec.strings = &onefile;
Packit Service 20376f
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_config_set_string(cfg, "diff.mnemonicprefix", "true"));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_index(&diff, g_repo, one, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(1, (int)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
	cl_assert_equal_s(expected1, buf.ptr);
Packit Service 20376f
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
	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(1, (int)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
	cl_assert_equal_s(expected2, buf.ptr);
Packit Service 20376f
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
Packit Service 20376f
	cl_git_pass(git_config_set_string(cfg, "diff.noprefix", "true"));
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, (int)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
	cl_assert_equal_s(expected3, buf.ptr);
Packit Service 20376f
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
Packit Service 20376f
	cl_git_pass(git_config_set_int32(cfg, "core.abbrev", 12));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_index(&diff, g_repo, one, NULL, &opts));
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(1, (int)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
	cl_assert_equal_s(expected4, buf.ptr);
Packit Service 20376f
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
	git_buf_free(&buf;;
Packit Service 20376f
	git_tree_free(one);
Packit Service 20376f
	git_config_free(cfg);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_diff_patch__hunks_have_correct_line_numbers(void)
Packit Service 20376f
{
Packit Service 20376f
	git_config *cfg;
Packit Service 20376f
	git_tree *head;
Packit Service 20376f
	git_diff_options opt = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_diff *diff;
Packit Service 20376f
	git_patch *patch;
Packit Service 20376f
	const git_diff_delta *delta;
Packit Service 20376f
	const git_diff_hunk *hunk;
Packit Service 20376f
	const git_diff_line *line;
Packit Service 20376f
	size_t hunklen;
Packit Service 20376f
	git_buf old_content = GIT_BUF_INIT, actual = GIT_BUF_INIT;
Packit Service 20376f
	const char *new_content = "The Song of Seven Cities\n------------------------\n\nI WAS Lord of Cities very sumptuously builded.\nSeven roaring Cities paid me tribute from afar.\nIvory their outposts were--the guardrooms of them gilded,\nAnd garrisoned with Amazons invincible in war.\n\nThis is some new text;\nNot as good as the old text;\nBut here it is.\n\nSo they warred and trafficked only yesterday, my Cities.\nTo-day there is no mark or mound of where my Cities stood.\nFor the River rose at midnight and it washed away my Cities.\nThey are evened with Atlantis and the towns before the Flood.\n\nRain on rain-gorged channels raised the water-levels round them,\nFreshet backed on freshet swelled and swept their world from sight,\nTill the emboldened floods linked arms and, flashing forward, drowned them--\nDrowned my Seven Cities and their peoples in one night!\n\nLow among the alders lie their derelict foundations,\nThe beams wherein they trusted and the plinths whereon they built--\nMy rulers and their treasure and their unborn populations,\nDead, destroyed, aborted, and defiled with mud and silt!\n\nAnother replacement;\nBreaking up the poem;\nGenerating some hunks.\n\nTo the sound of trumpets shall their seed restore my Cities\nWealthy and well-weaponed, that once more may I behold\nAll the world go softly when it walks before my Cities,\nAnd the horses and the chariots fleeing from them as of old!\n\n  -- Rudyard Kipling\n";
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("renames");
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_config_new(&cfg));
Packit Service 20376f
	git_repository_set_config(g_repo, cfg);
Packit Service 20376f
	git_config_free(cfg);
Packit Service 20376f
Packit Service 20376f
	git_repository_reinit_filesystem(g_repo, false);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(
Packit Service 20376f
		git_futils_readbuffer(&old_content, "renames/songof7cities.txt"));
Packit Service 20376f
Packit Service 20376f
	cl_git_rewritefile("renames/songof7cities.txt", new_content);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_repository_head_tree(&head, g_repo));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, head, &opt));
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_patch_from_diff(&patch, diff, 0));
Packit Service 20376f
	cl_assert((delta = git_patch_get_delta(patch)) != NULL);
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status);
Packit Service 20376f
	cl_assert_equal_i(2, (int)git_patch_num_hunks(patch));
Packit Service 20376f
Packit Service 20376f
	/* check hunk 0 */
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(
Packit Service 20376f
		git_patch_get_hunk(&hunk, &hunklen, patch, 0));
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(18, (int)hunklen);
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(6, (int)hunk->old_start);
Packit Service 20376f
	cl_assert_equal_i(15, (int)hunk->old_lines);
Packit Service 20376f
	cl_assert_equal_i(6, (int)hunk->new_start);
Packit Service 20376f
	cl_assert_equal_i(9, (int)hunk->new_lines);
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(18, (int)git_patch_num_lines_in_hunk(patch, 0));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 0));
Packit Service 20376f
	cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)line->origin);
Packit Service 20376f
	cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
Packit Service 20376f
	cl_assert_equal_s("Ivory their outposts were--the guardrooms of them gilded,\n", actual.ptr);
Packit Service 20376f
	cl_assert_equal_i(6, line->old_lineno);
Packit Service 20376f
	cl_assert_equal_i(6, line->new_lineno);
Packit Service 20376f
	cl_assert_equal_i(-1, line->content_offset);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 3));
Packit Service 20376f
	cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin);
Packit Service 20376f
	cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
Packit Service 20376f
	cl_assert_equal_s("All the world went softly when it walked before my Cities--\n", actual.ptr);
Packit Service 20376f
	cl_assert_equal_i(9, line->old_lineno);
Packit Service 20376f
	cl_assert_equal_i(-1, line->new_lineno);
Packit Service 20376f
	cl_assert_equal_i(252, line->content_offset);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 12));
Packit Service 20376f
	cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin);
Packit Service 20376f
	cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
Packit Service 20376f
	cl_assert_equal_s("This is some new text;\n", actual.ptr);
Packit Service 20376f
	cl_assert_equal_i(-1, line->old_lineno);
Packit Service 20376f
	cl_assert_equal_i(9, line->new_lineno);
Packit Service 20376f
	cl_assert_equal_i(252, line->content_offset);
Packit Service 20376f
Packit Service 20376f
	/* check hunk 1 */
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_patch_get_hunk(&hunk, &hunklen, patch, 1));
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(18, (int)hunklen);
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(31, (int)hunk->old_start);
Packit Service 20376f
	cl_assert_equal_i(15, (int)hunk->old_lines);
Packit Service 20376f
	cl_assert_equal_i(25, (int)hunk->new_start);
Packit Service 20376f
	cl_assert_equal_i(9, (int)hunk->new_lines);
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(18, (int)git_patch_num_lines_in_hunk(patch, 1));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 1, 0));
Packit Service 20376f
	cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)line->origin);
Packit Service 20376f
	cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
Packit Service 20376f
	cl_assert_equal_s("My rulers and their treasure and their unborn populations,\n", actual.ptr);
Packit Service 20376f
	cl_assert_equal_i(31, line->old_lineno);
Packit Service 20376f
	cl_assert_equal_i(25, line->new_lineno);
Packit Service 20376f
	cl_assert_equal_i(-1, line->content_offset);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 1, 3));
Packit Service 20376f
	cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin);
Packit Service 20376f
	cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
Packit Service 20376f
	cl_assert_equal_s("The Daughters of the Palace whom they cherished in my Cities,\n", actual.ptr);
Packit Service 20376f
	cl_assert_equal_i(34, line->old_lineno);
Packit Service 20376f
	cl_assert_equal_i(-1, line->new_lineno);
Packit Service 20376f
	cl_assert_equal_i(1468, line->content_offset);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 1, 12));
Packit Service 20376f
	cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin);
Packit Service 20376f
	cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
Packit Service 20376f
	cl_assert_equal_s("Another replacement;\n", actual.ptr);
Packit Service 20376f
	cl_assert_equal_i(-1, line->old_lineno);
Packit Service 20376f
	cl_assert_equal_i(28, line->new_lineno);
Packit Service 20376f
	cl_assert_equal_i(1066, line->content_offset);
Packit Service 20376f
Packit Service 20376f
	git_patch_free(patch);
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	/* Let's check line numbers when there is no newline */
Packit Service 20376f
Packit Service 20376f
	git_buf_rtrim(&old_content);
Packit Service 20376f
	cl_git_rewritefile("renames/songof7cities.txt", old_content.ptr);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, head, &opt));
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_patch_from_diff(&patch, diff, 0));
Packit Service 20376f
	cl_assert((delta = git_patch_get_delta(patch)) != NULL);
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status);
Packit Service 20376f
	cl_assert_equal_i(1, (int)git_patch_num_hunks(patch));
Packit Service 20376f
Packit Service 20376f
	/* check hunk 0 */
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_patch_get_hunk(&hunk, &hunklen, patch, 0));
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(6, (int)hunklen);
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(46, (int)hunk->old_start);
Packit Service 20376f
	cl_assert_equal_i(4, (int)hunk->old_lines);
Packit Service 20376f
	cl_assert_equal_i(46, (int)hunk->new_start);
Packit Service 20376f
	cl_assert_equal_i(4, (int)hunk->new_lines);
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(6, (int)git_patch_num_lines_in_hunk(patch, 0));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 1));
Packit Service 20376f
	cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)line->origin);
Packit Service 20376f
	cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
Packit Service 20376f
	cl_assert_equal_s("And the horses and the chariots fleeing from them as of old!\n", actual.ptr);
Packit Service 20376f
	cl_assert_equal_i(47, line->old_lineno);
Packit Service 20376f
	cl_assert_equal_i(47, line->new_lineno);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 2));
Packit Service 20376f
	cl_assert_equal_i(GIT_DIFF_LINE_CONTEXT, (int)line->origin);
Packit Service 20376f
	cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
Packit Service 20376f
	cl_assert_equal_s("\n", actual.ptr);
Packit Service 20376f
	cl_assert_equal_i(48, line->old_lineno);
Packit Service 20376f
	cl_assert_equal_i(48, line->new_lineno);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 3));
Packit Service 20376f
	cl_assert_equal_i(GIT_DIFF_LINE_DELETION, (int)line->origin);
Packit Service 20376f
	cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
Packit Service 20376f
	cl_assert_equal_s("  -- Rudyard Kipling\n", actual.ptr);
Packit Service 20376f
	cl_assert_equal_i(49, line->old_lineno);
Packit Service 20376f
	cl_assert_equal_i(-1, line->new_lineno);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 4));
Packit Service 20376f
	cl_assert_equal_i(GIT_DIFF_LINE_ADDITION, (int)line->origin);
Packit Service 20376f
	cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
Packit Service 20376f
	cl_assert_equal_s("  -- Rudyard Kipling", actual.ptr);
Packit Service 20376f
	cl_assert_equal_i(-1, line->old_lineno);
Packit Service 20376f
	cl_assert_equal_i(49, line->new_lineno);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_patch_get_line_in_hunk(&line, patch, 0, 5));
Packit Service 20376f
	cl_assert_equal_i(GIT_DIFF_LINE_DEL_EOFNL, (int)line->origin);
Packit Service 20376f
	cl_git_pass(git_buf_set(&actual, line->content, line->content_len));
Packit Service 20376f
	cl_assert_equal_s("\n\\ No newline at end of file\n", actual.ptr);
Packit Service 20376f
	cl_assert_equal_i(-1, line->old_lineno);
Packit Service 20376f
	cl_assert_equal_i(49, line->new_lineno);
Packit Service 20376f
Packit Service 20376f
	git_patch_free(patch);
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
Packit Service 20376f
	git_buf_free(&actual);
Packit Service 20376f
	git_buf_free(&old_content);
Packit Service 20376f
	git_tree_free(head);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static void check_single_patch_stats(
Packit Service 20376f
	git_repository *repo, size_t hunks,
Packit Service 20376f
	size_t adds, size_t dels, size_t ctxt, size_t *sizes,
Packit Service 20376f
	const char *expected)
Packit Service 20376f
{
Packit Service 20376f
	git_diff *diff;
Packit Service 20376f
	git_patch *patch;
Packit Service 20376f
	const git_diff_delta *delta;
Packit Service 20376f
	size_t actual_ctxt, actual_adds, actual_dels;
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_diff_index_to_workdir(&diff, repo, NULL, NULL));
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_patch_from_diff(&patch, diff, 0));
Packit Service 20376f
	cl_assert((delta = git_patch_get_delta(patch)) != NULL);
Packit Service 20376f
	cl_assert_equal_i(GIT_DELTA_MODIFIED, (int)delta->status);
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_i((int)hunks, (int)git_patch_num_hunks(patch));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass( git_patch_line_stats(
Packit Service 20376f
		&actual_ctxt, &actual_adds, &actual_dels, patch) );
Packit Service 20376f
Packit Service 20376f
	cl_assert_equal_sz(ctxt, actual_ctxt);
Packit Service 20376f
	cl_assert_equal_sz(adds, actual_adds);
Packit Service 20376f
	cl_assert_equal_sz(dels, actual_dels);
Packit Service 20376f
Packit Service 20376f
	if (expected != NULL) {
Packit Service 20376f
		git_buf buf = GIT_BUF_INIT;
Packit Service 20376f
		cl_git_pass(git_patch_to_buf(&buf, patch));
Packit Service 20376f
		cl_assert_equal_s(expected, buf.ptr);
Packit Service 20376f
		git_buf_free(&buf;;
Packit Service 20376f
Packit Service 20376f
		cl_assert_equal_sz(
Packit Service 20376f
			strlen(expected), git_patch_size(patch, 1, 1, 1));
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	if (sizes) {
Packit Service 20376f
		if (sizes[0])
Packit Service 20376f
			cl_assert_equal_sz(sizes[0], git_patch_size(patch, 0, 0, 0));
Packit Service 20376f
		if (sizes[1])
Packit Service 20376f
			cl_assert_equal_sz(sizes[1], git_patch_size(patch, 1, 0, 0));
Packit Service 20376f
		if (sizes[2])
Packit Service 20376f
			cl_assert_equal_sz(sizes[2], git_patch_size(patch, 1, 1, 0));
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	/* walk lines in hunk with basic sanity checks */
Packit Service 20376f
	for (; hunks > 0; --hunks) {
Packit Service 20376f
		size_t i, max_i;
Packit Service 20376f
		const git_diff_line *line;
Packit Service 20376f
		int last_new_lineno = -1, last_old_lineno = -1;
Packit Service 20376f
Packit Service 20376f
		max_i = git_patch_num_lines_in_hunk(patch, hunks - 1);
Packit Service 20376f
Packit Service 20376f
		for (i = 0; i < max_i; ++i) {
Packit Service 20376f
			int expected = 1;
Packit Service 20376f
Packit Service 20376f
			cl_git_pass(
Packit Service 20376f
				git_patch_get_line_in_hunk(&line, patch, hunks - 1, i));
Packit Service 20376f
Packit Service 20376f
			if (line->origin == GIT_DIFF_LINE_ADD_EOFNL ||
Packit Service 20376f
				line->origin == GIT_DIFF_LINE_DEL_EOFNL ||
Packit Service 20376f
				line->origin == GIT_DIFF_LINE_CONTEXT_EOFNL)
Packit Service 20376f
				expected = 0;
Packit Service 20376f
Packit Service 20376f
			if (line->old_lineno >= 0) {
Packit Service 20376f
				if (last_old_lineno >= 0)
Packit Service 20376f
					cl_assert_equal_i(
Packit Service 20376f
						expected, line->old_lineno - last_old_lineno);
Packit Service 20376f
				last_old_lineno = line->old_lineno;
Packit Service 20376f
			}
Packit Service 20376f
Packit Service 20376f
			if (line->new_lineno >= 0) {
Packit Service 20376f
				if (last_new_lineno >= 0)
Packit Service 20376f
					cl_assert_equal_i(
Packit Service 20376f
						expected, line->new_lineno - last_new_lineno);
Packit Service 20376f
				last_new_lineno = line->new_lineno;
Packit Service 20376f
			}
Packit Service 20376f
		}
Packit Service 20376f
	}
Packit Service 20376f
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_patch__line_counts_with_eofnl(void)
Packit Service 20376f
{
Packit Service 20376f
	git_config *cfg;
Packit Service 20376f
	git_buf content = GIT_BUF_INIT;
Packit Service 20376f
	const char *end;
Packit Service 20376f
	git_index *index;
Packit Service 20376f
	const char *expected =
Packit Service 20376f
		/* below is pasted output of 'git diff' with fn context removed */
Packit Service 20376f
		"diff --git a/songof7cities.txt b/songof7cities.txt\n"
Packit Service 20376f
		"index 378a7d9..3d0154e 100644\n"
Packit Service 20376f
		"--- a/songof7cities.txt\n"
Packit Service 20376f
		"+++ b/songof7cities.txt\n"
Packit Service 20376f
		"@@ -42,7 +42,7 @@ With peoples undefeated of the dark, enduring blood.\n"
Packit Service 20376f
		" \n"
Packit Service 20376f
		" To the sound of trumpets shall their seed restore my Cities\n"
Packit Service 20376f
		" Wealthy and well-weaponed, that once more may I behold\n"
Packit Service 20376f
		"-All the world go softly when it walks before my Cities,\n"
Packit Service 20376f
		"+#All the world go softly when it walks before my Cities,\n"
Packit Service 20376f
		" And the horses and the chariots fleeing from them as of old!\n"
Packit Service 20376f
		" \n"
Packit Service 20376f
		"   -- Rudyard Kipling\n"
Packit Service 20376f
		"\\ No newline at end of file\n";
Packit Service 20376f
	size_t expected_sizes[3] = { 115, 119 + 115 + 114, 119 + 115 + 114 + 71 };
Packit Service 20376f
Packit Service 20376f
	g_repo = cl_git_sandbox_init("renames");
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_config_new(&cfg));
Packit Service 20376f
	git_repository_set_config(g_repo, cfg);
Packit Service 20376f
	git_config_free(cfg);
Packit Service 20376f
Packit Service 20376f
	git_repository_reinit_filesystem(g_repo, false);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_futils_readbuffer(&content, "renames/songof7cities.txt"));
Packit Service 20376f
Packit Service 20376f
	/* remove first line */
Packit Service 20376f
Packit Service 20376f
	end = git_buf_cstr(&content) + git_buf_find(&content, '\n') + 1;
Packit Service 20376f
	git_buf_consume(&content, end);
Packit Service 20376f
	cl_git_rewritefile("renames/songof7cities.txt", content.ptr);
Packit Service 20376f
Packit Service 20376f
	check_single_patch_stats(g_repo, 1, 0, 1, 3, NULL, NULL);
Packit Service 20376f
Packit Service 20376f
	/* remove trailing whitespace */
Packit Service 20376f
Packit Service 20376f
	git_buf_rtrim(&content);
Packit Service 20376f
	cl_git_rewritefile("renames/songof7cities.txt", content.ptr);
Packit Service 20376f
Packit Service 20376f
	check_single_patch_stats(g_repo, 2, 1, 2, 6, NULL, NULL);
Packit Service 20376f
Packit Service 20376f
	/* add trailing whitespace */
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_repository_index(&index, g_repo));
Packit Service 20376f
	cl_git_pass(git_index_add_bypath(index, "songof7cities.txt"));
Packit Service 20376f
	cl_git_pass(git_index_write(index));
Packit Service 20376f
	git_index_free(index);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_buf_putc(&content, '\n'));
Packit Service 20376f
	cl_git_rewritefile("renames/songof7cities.txt", content.ptr);
Packit Service 20376f
Packit Service 20376f
	check_single_patch_stats(g_repo, 1, 1, 1, 3, NULL, NULL);
Packit Service 20376f
Packit Service 20376f
	/* no trailing whitespace as context line */
Packit Service 20376f
Packit Service 20376f
	{
Packit Service 20376f
		/* walk back a couple lines, make space and insert char */
Packit Service 20376f
		char *scan = content.ptr + content.size;
Packit Service 20376f
		int i;
Packit Service 20376f
Packit Service 20376f
		for (i = 0; i < 5; ++i) {
Packit Service 20376f
			for (--scan; scan > content.ptr && *scan != '\n'; --scan)
Packit Service 20376f
				/* seek to prev \n */;
Packit Service 20376f
		}
Packit Service 20376f
		cl_assert(scan > content.ptr);
Packit Service 20376f
Packit Service 20376f
		/* overwrite trailing \n with right-shifted content */
Packit Service 20376f
		memmove(scan + 1, scan, content.size - (scan - content.ptr) - 1);
Packit Service 20376f
		/* insert '#' char into space we created */
Packit Service 20376f
		scan[1] = '#';
Packit Service 20376f
	}
Packit Service 20376f
	cl_git_rewritefile("renames/songof7cities.txt", content.ptr);
Packit Service 20376f
Packit Service 20376f
	check_single_patch_stats(
Packit Service 20376f
		g_repo, 1, 1, 1, 6, expected_sizes, expected);
Packit Service 20376f
Packit Service 20376f
	git_buf_free(&content);
Packit Service 20376f
}