1 #include "clar_libgit2.h"
2 #include "checkout_helpers.h"
3 #include "../filter/crlf.h"
6 #include "git2/checkout.h"
7 #include "repository.h"
11 static git_repository
*g_repo
;
13 static const char *systype
;
14 static git_buf expected_fixture
= GIT_BUF_INIT
;
16 static int unlink_file(void *payload
, git_buf
*path
)
20 cl_assert(fn
= git_path_basename(path
->ptr
));
24 if (strcmp(fn
, ".git"))
25 cl_must_pass(p_unlink(path
->ptr
));
31 void test_checkout_crlf__initialize(void)
33 git_buf reponame
= GIT_BUF_INIT
;
35 g_repo
= cl_git_sandbox_init("crlf");
38 * remove the contents of the working directory so that we can
41 cl_git_pass(git_buf_puts(&reponame
, "crlf"));
42 cl_git_pass(git_path_direach(&reponame
, 0, unlink_file
, NULL
));
44 if (GIT_EOL_NATIVE
== GIT_EOL_CRLF
)
49 git_buf_dispose(&reponame
);
52 void test_checkout_crlf__cleanup(void)
54 cl_git_sandbox_cleanup();
56 if (expected_fixture
.size
) {
57 cl_fixture_cleanup(expected_fixture
.ptr
);
58 git_buf_dispose(&expected_fixture
);
69 static int compare_file(void *payload
, git_buf
*actual_path
)
71 git_buf expected_path
= GIT_BUF_INIT
;
72 git_buf actual_contents
= GIT_BUF_INIT
;
73 git_buf expected_contents
= GIT_BUF_INIT
;
74 struct compare_data
*cd
= payload
;
76 int cmp_git
, cmp_gitattributes
;
79 basename
= git_path_basename(actual_path
->ptr
);
80 cmp_git
= strcmp(basename
, ".git");
81 cmp_gitattributes
= strcmp(basename
, ".gitattributes");
83 if (cmp_git
== 0 || cmp_gitattributes
== 0) {
88 cl_git_pass(git_buf_joinpath(&expected_path
, cd
->dirname
, basename
));
90 if (!git_path_isfile(expected_path
.ptr
) ||
91 !git_path_isfile(actual_path
->ptr
))
94 if (git_futils_readbuffer(&actual_contents
, actual_path
->ptr
) < 0 ||
95 git_futils_readbuffer(&expected_contents
, expected_path
.ptr
) < 0)
98 if (actual_contents
.size
!= expected_contents
.size
)
101 if (memcmp(actual_contents
.ptr
, expected_contents
.ptr
, expected_contents
.size
) != 0)
108 git_buf details
= GIT_BUF_INIT
;
109 git_buf_printf(&details
, "filename=%s, system=%s, autocrlf=%s, attrs={%s}",
110 git_path_basename(actual_path
->ptr
), systype
, cd
->autocrlf
, cd
->attrs
);
111 clar__fail(__FILE__
, __LINE__
,
112 "checked out contents did not match expected", details
.ptr
, 0);
113 git_buf_dispose(&details
);
117 git_buf_dispose(&expected_contents
);
118 git_buf_dispose(&actual_contents
);
119 git_buf_dispose(&expected_path
);
124 static void test_checkout(const char *autocrlf
, const char *attrs
)
126 git_buf attrbuf
= GIT_BUF_INIT
;
127 git_buf expected_dirname
= GIT_BUF_INIT
;
128 git_buf systype_and_direction
= GIT_BUF_INIT
;
129 git_buf sandboxname
= GIT_BUF_INIT
;
130 git_buf reponame
= GIT_BUF_INIT
;
131 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
132 struct compare_data compare_data
= { NULL
, autocrlf
, attrs
};
135 cl_git_pass(git_buf_puts(&reponame
, "crlf"));
137 cl_git_pass(git_buf_puts(&systype_and_direction
, systype
));
138 cl_git_pass(git_buf_puts(&systype_and_direction
, "_to_workdir"));
140 cl_git_pass(git_buf_puts(&sandboxname
, "autocrlf_"));
141 cl_git_pass(git_buf_puts(&sandboxname
, autocrlf
));
144 cl_git_pass(git_buf_puts(&sandboxname
, ","));
146 for (c
= attrs
; *c
; c
++) {
148 cl_git_pass(git_buf_putc(&sandboxname
, ','));
150 cl_git_pass(git_buf_putc(&sandboxname
, '_'));
152 cl_git_pass(git_buf_putc(&sandboxname
, *c
));
155 cl_git_pass(git_buf_printf(&attrbuf
, "* %s\n", attrs
));
156 cl_git_mkfile("crlf/.gitattributes", attrbuf
.ptr
);
159 cl_repo_set_string(g_repo
, "core.autocrlf", autocrlf
);
161 cl_git_pass(git_buf_joinpath(&expected_dirname
, systype_and_direction
.ptr
, sandboxname
.ptr
));
162 cl_git_pass(git_buf_joinpath(&expected_fixture
, "crlf_data", expected_dirname
.ptr
));
163 cl_fixture_sandbox(expected_fixture
.ptr
);
165 opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
166 cl_git_pass(git_checkout_head(g_repo
, &opts
));
168 compare_data
.dirname
= sandboxname
.ptr
;
169 cl_git_pass(git_path_direach(&reponame
, 0, compare_file
, &compare_data
));
171 cl_fixture_cleanup(expected_fixture
.ptr
);
172 git_buf_dispose(&expected_fixture
);
174 git_buf_dispose(&attrbuf
);
175 git_buf_dispose(&expected_fixture
);
176 git_buf_dispose(&expected_dirname
);
177 git_buf_dispose(&sandboxname
);
178 git_buf_dispose(&systype_and_direction
);
179 git_buf_dispose(&reponame
);
182 static void empty_workdir(const char *name
)
184 git_vector contents
= GIT_VECTOR_INIT
;
190 cl_git_pass(git_path_dirload(&contents
, name
, 0, 0));
191 git_vector_foreach(&contents
, i
, fn
) {
192 cl_assert(basename
= git_path_basename(fn
));
193 cmp
= strncasecmp(basename
, ".git", 4);
198 cl_git_pass(p_unlink(fn
));
200 git_vector_free_deep(&contents
);
203 void test_checkout_crlf__matches_core_git(void)
205 const char *autocrlf
[] = { "true", "false", "input", NULL
};
206 const char *attrs
[] = { "", "-crlf", "-text", "eol=crlf", "eol=lf",
207 "text", "text eol=crlf", "text eol=lf",
208 "text=auto", "text=auto eol=crlf", "text=auto eol=lf",
212 for (a
= autocrlf
; *a
; a
++) {
213 for (b
= attrs
; *b
; b
++) {
214 empty_workdir("crlf");
215 test_checkout(*a
, *b
);
220 void test_checkout_crlf__detect_crlf_autocrlf_false(void)
222 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
223 opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
225 cl_repo_set_bool(g_repo
, "core.autocrlf", false);
227 git_checkout_head(g_repo
, &opts
);
229 check_file_contents("./crlf/all-lf", ALL_LF_TEXT_RAW
);
230 check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW
);
233 void test_checkout_crlf__autocrlf_false_index_size_is_unfiltered_size(void)
236 const git_index_entry
*entry
;
237 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
238 opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
240 cl_repo_set_bool(g_repo
, "core.autocrlf", false);
242 git_repository_index(&index
, g_repo
);
245 git_checkout_head(g_repo
, &opts
);
247 cl_assert((entry
= git_index_get_bypath(index
, "all-lf", 0)) != NULL
);
248 cl_assert(entry
->file_size
== strlen(ALL_LF_TEXT_RAW
));
250 cl_assert((entry
= git_index_get_bypath(index
, "all-crlf", 0)) != NULL
);
251 cl_assert(entry
->file_size
== strlen(ALL_CRLF_TEXT_RAW
));
253 git_index_free(index
);
256 void test_checkout_crlf__detect_crlf_autocrlf_true(void)
258 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
259 opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
261 cl_repo_set_bool(g_repo
, "core.autocrlf", true);
263 git_checkout_head(g_repo
, &opts
);
265 check_file_contents("./crlf/all-lf", ALL_LF_TEXT_AS_CRLF
);
266 check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW
);
269 void test_checkout_crlf__detect_crlf_autocrlf_true_utf8(void)
271 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
272 opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
274 cl_repo_set_bool(g_repo
, "core.autocrlf", true);
276 git_repository_set_head(g_repo
, "refs/heads/master");
277 git_checkout_head(g_repo
, &opts
);
279 check_file_contents("./crlf/few-utf8-chars-lf", FEW_UTF8_CRLF_RAW
);
280 check_file_contents("./crlf/many-utf8-chars-lf", MANY_UTF8_CRLF_RAW
);
282 check_file_contents("./crlf/few-utf8-chars-crlf", FEW_UTF8_CRLF_RAW
);
283 check_file_contents("./crlf/many-utf8-chars-crlf", MANY_UTF8_CRLF_RAW
);
286 void test_checkout_crlf__autocrlf_true_index_size_is_filtered_size(void)
289 const git_index_entry
*entry
;
290 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
291 opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
293 cl_repo_set_bool(g_repo
, "core.autocrlf", true);
295 git_repository_index(&index
, g_repo
);
298 git_checkout_head(g_repo
, &opts
);
300 cl_assert((entry
= git_index_get_bypath(index
, "all-lf", 0)) != NULL
);
302 cl_assert_equal_sz(strlen(ALL_LF_TEXT_AS_CRLF
), entry
->file_size
);
304 cl_assert((entry
= git_index_get_bypath(index
, "all-crlf", 0)) != NULL
);
305 cl_assert_equal_sz(strlen(ALL_CRLF_TEXT_RAW
), entry
->file_size
);
307 git_index_free(index
);
310 void test_checkout_crlf__with_ident(void)
313 const git_index_entry
*entry
;
315 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
316 opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
318 cl_git_mkfile("crlf/.gitattributes",
319 "*.txt text\n*.bin binary\n"
320 "*.crlf text eol=crlf\n"
322 "*.ident text ident\n"
323 "*.identcrlf ident text eol=crlf\n"
324 "*.identlf ident text eol=lf\n");
326 cl_repo_set_bool(g_repo
, "core.autocrlf", true);
328 /* add files with $Id$ */
330 cl_git_mkfile("crlf/lf.ident", ALL_LF_TEXT_RAW
"\n$Id: initial content$\n");
331 cl_git_mkfile("crlf/crlf.ident", ALL_CRLF_TEXT_RAW
"\r\n$Id$\r\n\r\n");
332 cl_git_mkfile("crlf/more1.identlf", "$Id$\n" MORE_LF_TEXT_RAW
);
333 cl_git_mkfile("crlf/more2.identcrlf", "\r\n$Id: \f$\r\n" MORE_CRLF_TEXT_RAW
);
335 cl_git_pass(git_repository_index(&index
, g_repo
));
336 cl_git_pass(git_index_add_bypath(index
, "lf.ident"));
337 cl_git_pass(git_index_add_bypath(index
, "crlf.ident"));
338 cl_git_pass(git_index_add_bypath(index
, "more1.identlf"));
339 cl_git_pass(git_index_add_bypath(index
, "more2.identcrlf"));
340 cl_repo_commit_from_index(NULL
, g_repo
, NULL
, 0, "Some ident files\n");
342 git_checkout_head(g_repo
, &opts
);
344 /* check that blobs have $Id$ */
346 cl_assert((entry
= git_index_get_bypath(index
, "lf.ident", 0)));
347 cl_git_pass(git_blob_lookup(&blob
, g_repo
, &entry
->id
));
349 ALL_LF_TEXT_RAW
"\n$Id$\n", git_blob_rawcontent(blob
));
352 cl_assert((entry
= git_index_get_bypath(index
, "more2.identcrlf", 0)));
353 cl_git_pass(git_blob_lookup(&blob
, g_repo
, &entry
->id
));
355 "\n$Id$\n" MORE_CRLF_TEXT_AS_LF
, git_blob_rawcontent(blob
));
358 /* check that filesystem is initially untouched - matching core Git */
360 cl_assert_equal_file(
361 ALL_LF_TEXT_RAW
"\n$Id: initial content$\n", 0, "crlf/lf.ident");
363 /* check that forced checkout rewrites correctly */
365 p_unlink("crlf/lf.ident");
366 p_unlink("crlf/crlf.ident");
367 p_unlink("crlf/more1.identlf");
368 p_unlink("crlf/more2.identcrlf");
370 cl_git_pass(git_checkout_head(g_repo
, &opts
));
372 cl_assert_equal_file(
374 "\r\n$Id: fcf6d4d9c212dc66563b1171b1cd99953c756467 $\r\n",
376 cl_assert_equal_file(
378 "\r\n$Id: f2c66ad9b2b5a734d9bf00d5000cc10a62b8a857 $\r\n\r\n",
379 0, "crlf/crlf.ident");
381 cl_assert_equal_file(
382 "$Id: f7830382dac1f1583422be5530fdfbd26289431b $\n"
383 MORE_LF_TEXT_AS_LF
, 0, "crlf/more1.identlf");
385 cl_assert_equal_file(
386 "\r\n$Id: 74677a68413012ce8d7e7cfc3f12603df3a3eac4 $\r\n"
387 MORE_CRLF_TEXT_AS_CRLF
, 0, "crlf/more2.identcrlf");
389 git_index_free(index
);
392 void test_checkout_crlf__autocrlf_false_no_attrs(void)
394 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
395 opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
397 cl_repo_set_bool(g_repo
, "core.autocrlf", false);
399 cl_git_pass(git_checkout_head(g_repo
, &opts
));
401 check_file_contents("./crlf/all-lf", ALL_LF_TEXT_RAW
);
402 check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW
);
405 void test_checkout_crlf__autocrlf_true_no_attrs(void)
407 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
408 opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
410 cl_repo_set_bool(g_repo
, "core.autocrlf", true);
412 cl_git_pass(git_checkout_head(g_repo
, &opts
));
414 check_file_contents("./crlf/all-lf", ALL_LF_TEXT_AS_CRLF
);
415 check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_AS_CRLF
);
418 void test_checkout_crlf__autocrlf_input_no_attrs(void)
420 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
421 opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
423 cl_repo_set_string(g_repo
, "core.autocrlf", "input");
425 cl_git_pass(git_checkout_head(g_repo
, &opts
));
427 check_file_contents("./crlf/all-lf", ALL_LF_TEXT_RAW
);
428 check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW
);
431 void test_checkout_crlf__autocrlf_false_text_auto_attr(void)
433 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
434 opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
436 cl_git_mkfile("./crlf/.gitattributes", "* text=auto\n");
438 cl_repo_set_bool(g_repo
, "core.autocrlf", false);
440 cl_git_pass(git_checkout_head(g_repo
, &opts
));
442 if (GIT_EOL_NATIVE
== GIT_EOL_CRLF
) {
443 check_file_contents("./crlf/all-lf", ALL_LF_TEXT_AS_CRLF
);
444 check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_AS_CRLF
);
446 check_file_contents("./crlf/all-lf", ALL_LF_TEXT_RAW
);
447 check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW
);
451 void test_checkout_crlf__autocrlf_true_text_auto_attr(void)
453 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
454 opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
456 cl_git_mkfile("./crlf/.gitattributes", "* text=auto\n");
458 cl_repo_set_bool(g_repo
, "core.autocrlf", true);
460 cl_git_pass(git_checkout_head(g_repo
, &opts
));
462 check_file_contents("./crlf/all-lf", ALL_LF_TEXT_AS_CRLF
);
463 check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_AS_CRLF
);
466 void test_checkout_crlf__autocrlf_input_text_auto_attr(void)
468 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
469 opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
471 cl_git_mkfile("./crlf/.gitattributes", "* text=auto\n");
473 cl_repo_set_string(g_repo
, "core.autocrlf", "input");
475 cl_git_pass(git_checkout_head(g_repo
, &opts
));
477 check_file_contents("./crlf/all-lf", ALL_LF_TEXT_RAW
);
478 check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW
);
481 void test_checkout_crlf__can_write_empty_file(void)
483 git_checkout_options opts
= GIT_CHECKOUT_OPTIONS_INIT
;
484 opts
.checkout_strategy
= GIT_CHECKOUT_FORCE
;
486 cl_repo_set_bool(g_repo
, "core.autocrlf", true);
488 cl_git_pass(git_repository_set_head(g_repo
, "refs/heads/empty-files"));
489 cl_git_pass(git_checkout_head(g_repo
, &opts
));
491 check_file_contents("./crlf/test1.txt", "");
493 check_file_contents("./crlf/test2.txt", "test2.txt's content\r\n");
495 check_file_contents("./crlf/test3.txt", "");