drivers.c 9.48 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#include "clar_libgit2.h"
#include "diff_helpers.h"
#include "repository.h"
#include "diff_driver.h"

static git_repository *g_repo = NULL;

void test_diff_drivers__initialize(void)
{
}

void test_diff_drivers__cleanup(void)
{
	cl_git_sandbox_cleanup();
	g_repo = NULL;
}

18
static void overwrite_filemode(const char *expected, git_buf *actual)
19
{
20 21 22 23 24 25 26 27 28
	size_t offset;
	char *found;

	found = strstr(expected, "100644");
	if (!found)
		return;

	offset = ((const char *)found) - expected;
	if (actual->size < offset + 6)
29 30
		return;

31 32
	if (memcmp(&actual->ptr[offset], "100644", 6) != 0)
		memcpy(&actual->ptr[offset], "100644", 6);
33 34
}

35 36
void test_diff_drivers__patterns(void)
{
37
	git_config *cfg;
38 39
	const char *one_sha = "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13";
	git_tree *one;
40 41
	git_diff *diff;
	git_patch *patch;
42
	git_buf actual = GIT_BUF_INIT;
43 44 45 46 47 48 49 50 51 52 53 54
	const char *expected0 = "diff --git a/untimely.txt b/untimely.txt\nindex 9a69d96..57fd0cf 100644\n--- a/untimely.txt\n+++ b/untimely.txt\n@@ -22,3 +22,5 @@ Comes through the blood of the vanguards who\n   dreamed--too soon--it had sounded.\r\n \r\n                 -- Rudyard Kipling\r\n+\r\n+Some new stuff\r\n";
	const char *expected1 = "diff --git a/untimely.txt b/untimely.txt\nindex 9a69d96..57fd0cf 100644\nBinary files a/untimely.txt and b/untimely.txt differ\n";
	const char *expected2 = "diff --git a/untimely.txt b/untimely.txt\nindex 9a69d96..57fd0cf 100644\n--- a/untimely.txt\n+++ b/untimely.txt\n@@ -22,3 +22,5 @@ Heaven delivers on earth the Hour that cannot be\n   dreamed--too soon--it had sounded.\r\n \r\n                 -- Rudyard Kipling\r\n+\r\n+Some new stuff\r\n";

	g_repo = cl_git_sandbox_init("renames");

	one = resolve_commit_oid_to_tree(g_repo, one_sha);

	/* no diff */

	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL));
	cl_assert_equal_i(0, (int)git_diff_num_deltas(diff));
55
	git_diff_free(diff);
56 57 58 59 60 61 62 63

	/* default diff */

	cl_git_append2file("renames/untimely.txt", "\r\nSome new stuff\r\n");

	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL));
	cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));

Russell Belfer committed
64
	cl_git_pass(git_patch_from_diff(&patch, diff, 0));
65 66
	cl_git_pass(git_patch_to_buf(&actual, patch));
	cl_assert_equal_s(expected0, actual.ptr);
67

68
	git_buf_dispose(&actual);
69 70
	git_patch_free(patch);
	git_diff_free(diff);
71 72 73 74 75 76 77 78

	/* attribute diff set to false */

	cl_git_rewritefile("renames/.gitattributes", "untimely.txt -diff\n");

	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL));
	cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));

Russell Belfer committed
79
	cl_git_pass(git_patch_from_diff(&patch, diff, 0));
80 81
	cl_git_pass(git_patch_to_buf(&actual, patch));
	cl_assert_equal_s(expected1, actual.ptr);
82

83
	git_buf_dispose(&actual);
84 85
	git_patch_free(patch);
	git_diff_free(diff);
86 87 88 89 90 91 92 93

	/* attribute diff set to unconfigured value (should use default) */

	cl_git_rewritefile("renames/.gitattributes", "untimely.txt diff=kipling0\n");

	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL));
	cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));

Russell Belfer committed
94
	cl_git_pass(git_patch_from_diff(&patch, diff, 0));
95 96
	cl_git_pass(git_patch_to_buf(&actual, patch));
	cl_assert_equal_s(expected0, actual.ptr);
97

98
	git_buf_dispose(&actual);
99 100
	git_patch_free(patch);
	git_diff_free(diff);
101 102 103

	/* let's define that driver */

104 105 106
	cl_git_pass(git_repository_config(&cfg, g_repo));
	cl_git_pass(git_config_set_bool(cfg, "diff.kipling0.binary", 1));
	git_config_free(cfg);
107 108 109 110

	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL));
	cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));

Russell Belfer committed
111
	cl_git_pass(git_patch_from_diff(&patch, diff, 0));
112 113
	cl_git_pass(git_patch_to_buf(&actual, patch));
	cl_assert_equal_s(expected1, actual.ptr);
114

115
	git_buf_dispose(&actual);
116 117
	git_patch_free(patch);
	git_diff_free(diff);
118 119 120 121 122 123

	/* let's use a real driver with some regular expressions */

	git_diff_driver_registry_free(g_repo->diff_drivers);
	g_repo->diff_drivers = NULL;

124 125
	cl_git_pass(git_repository_config(&cfg, g_repo));
	cl_git_pass(git_config_set_bool(cfg, "diff.kipling0.binary", 0));
126
	cl_git_pass(git_config_set_string(cfg, "diff.kipling0.xfuncname", "^H.*$"));
127
	git_config_free(cfg);
128 129 130 131

	cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, one, NULL));
	cl_assert_equal_i(1, (int)git_diff_num_deltas(diff));

Russell Belfer committed
132
	cl_git_pass(git_patch_from_diff(&patch, diff, 0));
133 134
	cl_git_pass(git_patch_to_buf(&actual, patch));
	cl_assert_equal_s(expected2, actual.ptr);
135

136
	git_buf_dispose(&actual);
137 138
	git_patch_free(patch);
	git_diff_free(diff);
139 140 141 142

	git_tree_free(one);
}

143 144 145 146
void test_diff_drivers__long_lines(void)
{
	const char *base = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non nisi ligula. Ut viverra enim sed lobortis suscipit.\nPhasellus eget erat odio. Praesent at est iaculis, ultricies augue vel, dignissim risus. Suspendisse at nisi quis turpis fringilla rutrum id sit amet nulla.\nNam eget dolor fermentum, aliquet nisl at, convallis tellus. Pellentesque rhoncus erat enim, id porttitor elit euismod quis.\nMauris sollicitudin magna odio, non egestas libero vehicula ut. Etiam et quam velit. Fusce eget libero rhoncus, ultricies felis sit amet, egestas purus.\nAliquam in semper tellus. Pellentesque adipiscing rutrum velit, quis malesuada lacus consequat eget.\n";
	git_index *idx;
147 148
	git_diff *diff;
	git_patch *patch;
149
	git_buf actual = GIT_BUF_INIT;
150 151 152 153 154 155 156 157 158 159 160 161 162 163
	const char *expected = "diff --git a/longlines.txt b/longlines.txt\nindex c1ce6ef..0134431 100644\n--- a/longlines.txt\n+++ b/longlines.txt\n@@ -3,3 +3,5 @@ Phasellus eget erat odio. Praesent at est iaculis, ultricies augue vel, dignissi\n Nam eget dolor fermentum, aliquet nisl at, convallis tellus. Pellentesque rhoncus erat enim, id porttitor elit euismod quis.\n Mauris sollicitudin magna odio, non egestas libero vehicula ut. Etiam et quam velit. Fusce eget libero rhoncus, ultricies felis sit amet, egestas purus.\n Aliquam in semper tellus. Pellentesque adipiscing rutrum velit, quis malesuada lacus consequat eget.\n+newline\n+newline\n";

	g_repo = cl_git_sandbox_init("empty_standard_repo");

	cl_git_mkfile("empty_standard_repo/longlines.txt", base);
	cl_git_pass(git_repository_index(&idx, g_repo));
	cl_git_pass(git_index_add_bypath(idx, "longlines.txt"));
	cl_git_pass(git_index_write(idx));
	git_index_free(idx);

	cl_git_append2file("empty_standard_repo/longlines.txt", "newline\nnewline\n");

	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL));
	cl_assert_equal_sz(1, git_diff_num_deltas(diff));
Russell Belfer committed
164
	cl_git_pass(git_patch_from_diff(&patch, diff, 0));
165
	cl_git_pass(git_patch_to_buf(&actual, patch));
166

167
	/* if chmod not supported, overwrite mode bits since anything is possible */
168
	overwrite_filemode(expected, &actual);
169

170
	cl_assert_equal_s(expected, actual.ptr);
171

172
	git_buf_dispose(&actual);
173 174
	git_patch_free(patch);
	git_diff_free(diff);
175 176
}

177 178 179 180
void test_diff_drivers__builtins(void)
{
	git_diff *diff;
	git_patch *patch;
181
	git_buf file = GIT_BUF_INIT, actual = GIT_BUF_INIT, expected = GIT_BUF_INIT;
182
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
183 184 185
	git_vector files = GIT_VECTOR_INIT;
	size_t i;
	char *path, *extension;
186

187
	g_repo = cl_git_sandbox_init("userdiff");
188

189
	cl_git_pass(git_path_dirload(&files, "userdiff/files", 9, 0));
190

191 192 193
	opts.interhunk_lines = 1;
	opts.context_lines = 1;
	opts.pathspec.count = 1;
194

195 196 197 198 199
	git_vector_foreach(&files, i, path) {
		if (git__prefixcmp(path, "files/file."))
			continue;
		extension = path + strlen("files/file.");
		opts.pathspec.strings = &path;
200

201
		/* do diff with no special driver */
202

203 204 205 206
		cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
		cl_assert_equal_sz(1, git_diff_num_deltas(diff));
		cl_git_pass(git_patch_from_diff(&patch, diff, 0));
		cl_git_pass(git_patch_to_buf(&actual, patch));
207

208
		git_buf_sets(&expected, "userdiff/expected/nodriver/diff.");
209
		git_buf_puts(&expected, extension);
210
		cl_git_pass(git_futils_readbuffer(&expected, expected.ptr));
211

212
		overwrite_filemode(expected.ptr, &actual);
213

214
		cl_assert_equal_s(expected.ptr, actual.ptr);
215

216 217 218
		git_buf_clear(&actual);
		git_patch_free(patch);
		git_diff_free(diff);
219

220
		/* do diff with driver */
221

222 223
		{
			FILE *fp = fopen("userdiff/.gitattributes", "w");
224
			fprintf(fp, "*.%s diff=%s\n", extension, extension);
225 226
			fclose(fp);
		}
227

228 229 230 231 232 233
		cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
		cl_assert_equal_sz(1, git_diff_num_deltas(diff));
		cl_git_pass(git_patch_from_diff(&patch, diff, 0));
		cl_git_pass(git_patch_to_buf(&actual, patch));

		git_buf_sets(&expected, "userdiff/expected/driver/diff.");
234
		git_buf_puts(&expected, extension);
235 236 237
		cl_git_pass(git_futils_readbuffer(&expected, expected.ptr));

		overwrite_filemode(expected.ptr, &actual);
238

239
		cl_assert_equal_s(expected.ptr, actual.ptr);
240

241 242 243
		git_buf_clear(&actual);
		git_patch_free(patch);
		git_diff_free(diff);
244 245

		git__free(path);
246
	}
247

248 249 250
	git_buf_dispose(&file);
	git_buf_dispose(&actual);
	git_buf_dispose(&expected);
251
	git_vector_free(&files);
252
}
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278

void test_diff_drivers__invalid_pattern(void)
{
	git_config *cfg;
	git_index *idx;
	git_diff *diff;
	git_patch *patch;
	git_diff_options opts = GIT_DIFF_OPTIONS_INIT;

	g_repo = cl_git_sandbox_init("userdiff");
	cl_git_mkfile("userdiff/.gitattributes", "*.storyboard diff=storyboard\n");

	cl_git_pass(git_repository_config__weakptr(&cfg, g_repo));
	cl_git_pass(git_config_set_string(cfg, "diff.storyboard.xfuncname", "<!--(.*?)-->"));

	cl_git_mkfile("userdiff/dummy.storyboard", "");
	cl_git_pass(git_repository_index__weakptr(&idx, g_repo));
	cl_git_pass(git_index_add_bypath(idx, "dummy.storyboard"));
	cl_git_mkfile("userdiff/dummy.storyboard", "some content\n");

	cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
	cl_git_pass(git_patch_from_diff(&patch, diff, 0));

	git_patch_free(patch);
	git_diff_free(diff);
}