]>
Commit | Line | Data |
---|---|---|
6c106eec BS |
1 | #include "clar_libgit2.h" |
2 | #include "index.h" | |
3 | ||
a8122b5d RB |
4 | static const size_t index_entry_count = 109; |
5 | static const size_t index_entry_count_2 = 1437; | |
6c106eec BS |
6 | #define TEST_INDEX_PATH cl_fixture("testrepo.git/index") |
7 | #define TEST_INDEX2_PATH cl_fixture("gitgit.index") | |
8 | #define TEST_INDEXBIG_PATH cl_fixture("big.index") | |
3d523345 | 9 | #define TEST_INDEXBAD_PATH cl_fixture("bad.index") |
6c106eec BS |
10 | |
11 | ||
8e5a8ef8 | 12 | /* Suite data */ |
6c106eec | 13 | struct test_entry { |
11d9f6b3 | 14 | size_t index; |
6c106eec | 15 | char path[128]; |
22a2d3d5 | 16 | off64_t file_size; |
6c106eec BS |
17 | git_time_t mtime; |
18 | }; | |
19 | ||
b482c420 | 20 | static struct test_entry test_entries[] = { |
6c106eec | 21 | {4, "Makefile", 5064, 0x4C3F7F33}, |
6c106eec | 22 | {6, "git.git-authors", 2709, 0x4C3F7F33}, |
ac3d33df JK |
23 | {36, "src/index.c", 10014, 0x4C43368D}, |
24 | {48, "src/revobject.h", 1448, 0x4C3F7FE2}, | |
25 | {62, "tests/Makefile", 2631, 0x4C3F7F33} | |
6c106eec BS |
26 | }; |
27 | ||
8e5a8ef8 | 28 | /* Helpers */ |
270303ca | 29 | static void copy_file(const char *src, const char *dst) |
6c106eec | 30 | { |
e579e0f7 | 31 | git_str source_buf = GIT_STR_INIT; |
6c106eec | 32 | git_file dst_fd; |
6c106eec | 33 | |
270303ca | 34 | cl_git_pass(git_futils_readbuffer(&source_buf, src)); |
6c106eec | 35 | |
8e5a8ef8 | 36 | dst_fd = git_futils_creat_withpath(dst, 0777, 0666); /* -V536 */ |
6c106eec BS |
37 | if (dst_fd < 0) |
38 | goto cleanup; | |
39 | ||
270303ca | 40 | cl_git_pass(p_write(dst_fd, source_buf.ptr, source_buf.size)); |
6c106eec BS |
41 | |
42 | cleanup: | |
e579e0f7 | 43 | git_str_dispose(&source_buf); |
6c106eec | 44 | p_close(dst_fd); |
6c106eec BS |
45 | } |
46 | ||
270303ca | 47 | static void files_are_equal(const char *a, const char *b) |
6c106eec | 48 | { |
e579e0f7 MB |
49 | git_str buf_a = GIT_STR_INIT; |
50 | git_str buf_b = GIT_STR_INIT; | |
270303ca | 51 | int pass; |
6c106eec | 52 | |
e172cf08 | 53 | if (git_futils_readbuffer(&buf_a, a) < 0) |
270303ca | 54 | cl_assert(0); |
6c106eec | 55 | |
e172cf08 | 56 | if (git_futils_readbuffer(&buf_b, b) < 0) { |
e579e0f7 | 57 | git_str_dispose(&buf_a); |
270303ca | 58 | cl_assert(0); |
6c106eec BS |
59 | } |
60 | ||
270303ca | 61 | pass = (buf_a.size == buf_b.size && !memcmp(buf_a.ptr, buf_b.ptr, buf_a.size)); |
6c106eec | 62 | |
e579e0f7 MB |
63 | git_str_dispose(&buf_a); |
64 | git_str_dispose(&buf_b); | |
13ed2966 MS |
65 | |
66 | cl_assert(pass); | |
6c106eec BS |
67 | } |
68 | ||
69 | ||
8e5a8ef8 | 70 | /* Fixture setup and teardown */ |
6c106eec BS |
71 | void test_index_tests__initialize(void) |
72 | { | |
73 | } | |
74 | ||
ac3d33df JK |
75 | void test_index_tests__cleanup(void) |
76 | { | |
77 | cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_UNSAVED_INDEX_SAFETY, 0)); | |
78 | } | |
79 | ||
6c106eec BS |
80 | void test_index_tests__empty_index(void) |
81 | { | |
82 | git_index *index; | |
83 | ||
84 | cl_git_pass(git_index_open(&index, "in-memory-index")); | |
85 | cl_assert(index->on_disk == 0); | |
86 | ||
87 | cl_assert(git_index_entrycount(index) == 0); | |
882c7742 | 88 | cl_assert(git_vector_is_sorted(&index->entries)); |
6c106eec BS |
89 | |
90 | git_index_free(index); | |
91 | } | |
92 | ||
93 | void test_index_tests__default_test_index(void) | |
94 | { | |
95 | git_index *index; | |
96 | unsigned int i; | |
97 | git_index_entry **entries; | |
98 | ||
99 | cl_git_pass(git_index_open(&index, TEST_INDEX_PATH)); | |
100 | cl_assert(index->on_disk); | |
101 | ||
a8122b5d | 102 | cl_assert(git_index_entrycount(index) == index_entry_count); |
882c7742 | 103 | cl_assert(git_vector_is_sorted(&index->entries)); |
6c106eec BS |
104 | |
105 | entries = (git_index_entry **)index->entries.contents; | |
106 | ||
b482c420 | 107 | for (i = 0; i < ARRAY_SIZE(test_entries); ++i) { |
34b8eafc | 108 | git_index_entry *e = entries[test_entries[i].index]; |
6c106eec | 109 | |
34b8eafc | 110 | cl_assert_equal_s(e->path, test_entries[i].path); |
46c84c72 CMN |
111 | cl_assert_equal_i(e->mtime.seconds, test_entries[i].mtime); |
112 | cl_assert_equal_i(e->file_size, test_entries[i].file_size); | |
6c106eec BS |
113 | } |
114 | ||
115 | git_index_free(index); | |
116 | } | |
117 | ||
118 | void test_index_tests__gitgit_index(void) | |
119 | { | |
120 | git_index *index; | |
121 | ||
122 | cl_git_pass(git_index_open(&index, TEST_INDEX2_PATH)); | |
123 | cl_assert(index->on_disk); | |
124 | ||
a8122b5d | 125 | cl_assert(git_index_entrycount(index) == index_entry_count_2); |
882c7742 | 126 | cl_assert(git_vector_is_sorted(&index->entries)); |
6c106eec BS |
127 | cl_assert(index->tree != NULL); |
128 | ||
129 | git_index_free(index); | |
130 | } | |
131 | ||
132 | void test_index_tests__find_in_existing(void) | |
133 | { | |
134 | git_index *index; | |
135 | unsigned int i; | |
136 | ||
137 | cl_git_pass(git_index_open(&index, TEST_INDEX_PATH)); | |
138 | ||
b482c420 | 139 | for (i = 0; i < ARRAY_SIZE(test_entries); ++i) { |
34b8eafc | 140 | size_t idx; |
11d9f6b3 | 141 | |
34b8eafc | 142 | cl_assert(!git_index_find(&idx, index, test_entries[i].path)); |
143 | cl_assert(idx == test_entries[i].index); | |
6c106eec BS |
144 | } |
145 | ||
146 | git_index_free(index); | |
147 | } | |
148 | ||
149 | void test_index_tests__find_in_empty(void) | |
150 | { | |
151 | git_index *index; | |
152 | unsigned int i; | |
153 | ||
154 | cl_git_pass(git_index_open(&index, "fake-index")); | |
155 | ||
b482c420 | 156 | for (i = 0; i < ARRAY_SIZE(test_entries); ++i) { |
34b8eafc | 157 | cl_assert(GIT_ENOTFOUND == git_index_find(NULL, index, test_entries[i].path)); |
6c106eec BS |
158 | } |
159 | ||
160 | git_index_free(index); | |
161 | } | |
162 | ||
c097f717 LY |
163 | void test_index_tests__find_prefix(void) |
164 | { | |
165 | git_index *index; | |
166 | const git_index_entry *entry; | |
167 | size_t pos; | |
168 | ||
169 | cl_git_pass(git_index_open(&index, TEST_INDEX_PATH)); | |
170 | ||
171 | cl_git_pass(git_index_find_prefix(&pos, index, "src")); | |
172 | entry = git_index_get_byindex(index, pos); | |
173 | cl_assert(git__strcmp(entry->path, "src/block-sha1/sha1.c") == 0); | |
174 | ||
175 | cl_git_pass(git_index_find_prefix(&pos, index, "src/co")); | |
176 | entry = git_index_get_byindex(index, pos); | |
177 | cl_assert(git__strcmp(entry->path, "src/commit.c") == 0); | |
178 | ||
179 | cl_assert(GIT_ENOTFOUND == git_index_find_prefix(NULL, index, "blah")); | |
180 | ||
181 | git_index_free(index); | |
182 | } | |
183 | ||
6c106eec BS |
184 | void test_index_tests__write(void) |
185 | { | |
186 | git_index *index; | |
187 | ||
270303ca | 188 | copy_file(TEST_INDEXBIG_PATH, "index_rewrite"); |
6c106eec BS |
189 | |
190 | cl_git_pass(git_index_open(&index, "index_rewrite")); | |
191 | cl_assert(index->on_disk); | |
192 | ||
193 | cl_git_pass(git_index_write(index)); | |
270303ca | 194 | files_are_equal(TEST_INDEXBIG_PATH, "index_rewrite"); |
6c106eec BS |
195 | |
196 | git_index_free(index); | |
197 | ||
198 | p_unlink("index_rewrite"); | |
199 | } | |
200 | ||
201 | void test_index_tests__sort0(void) | |
202 | { | |
e579e0f7 | 203 | /* sort the entries in an index */ |
8e5a8ef8 | 204 | |
6c106eec BS |
205 | /* |
206 | * TODO: This no longer applies: | |
207 | * index sorting in Git uses some specific changes to the way | |
208 | * directories are sorted. | |
209 | * | |
e579e0f7 | 210 | * We need to specifically check for this by creating a new |
6c106eec BS |
211 | * index, adding entries in random order and then |
212 | * checking for consistency | |
213 | */ | |
214 | } | |
215 | ||
216 | void test_index_tests__sort1(void) | |
217 | { | |
e579e0f7 | 218 | /* sort the entries in an empty index */ |
6c106eec BS |
219 | git_index *index; |
220 | ||
221 | cl_git_pass(git_index_open(&index, "fake-index")); | |
222 | ||
223 | /* FIXME: this test is slightly dumb */ | |
882c7742 | 224 | cl_assert(git_vector_is_sorted(&index->entries)); |
6c106eec BS |
225 | |
226 | git_index_free(index); | |
227 | } | |
228 | ||
f6fded8f VM |
229 | static void cleanup_myrepo(void *opaque) |
230 | { | |
231 | GIT_UNUSED(opaque); | |
232 | cl_fixture_cleanup("myrepo"); | |
233 | } | |
234 | ||
6c106eec BS |
235 | void test_index_tests__add(void) |
236 | { | |
f6fded8f VM |
237 | git_index *index; |
238 | git_filebuf file = GIT_FILEBUF_INIT; | |
239 | git_repository *repo; | |
240 | const git_index_entry *entry; | |
241 | git_oid id1; | |
6c106eec | 242 | |
f6fded8f | 243 | cl_set_cleanup(&cleanup_myrepo, NULL); |
6c106eec | 244 | |
e579e0f7 | 245 | /* Initialize a new repository */ |
f6fded8f | 246 | cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); |
6c106eec | 247 | |
f6fded8f VM |
248 | /* Ensure we're the only guy in the room */ |
249 | cl_git_pass(git_repository_index(&index, repo)); | |
250 | cl_assert(git_index_entrycount(index) == 0); | |
6c106eec | 251 | |
f6fded8f VM |
252 | /* Create a new file in the working directory */ |
253 | cl_git_pass(git_futils_mkpath2file("myrepo/test.txt", 0777)); | |
1d3a8aeb | 254 | cl_git_pass(git_filebuf_open(&file, "myrepo/test.txt", 0, 0666)); |
f6fded8f | 255 | cl_git_pass(git_filebuf_write(&file, "hey there\n", 10)); |
1d3a8aeb | 256 | cl_git_pass(git_filebuf_commit(&file)); |
6c106eec | 257 | |
f6fded8f VM |
258 | /* Store the expected hash of the file/blob |
259 | * This has been generated by executing the following | |
260 | * $ echo "hey there" | git hash-object --stdin | |
261 | */ | |
262 | cl_git_pass(git_oid_fromstr(&id1, "a8233120f6ad708f843d861ce2b7228ec4e3dec6")); | |
6c106eec | 263 | |
f6fded8f | 264 | /* Add the new file to the index */ |
25743bd7 | 265 | cl_git_pass(git_index_add_bypath(index, "test.txt")); |
6c106eec | 266 | |
f6fded8f VM |
267 | /* Wow... it worked! */ |
268 | cl_assert(git_index_entrycount(index) == 1); | |
269 | entry = git_index_get_byindex(index, 0); | |
6c106eec | 270 | |
f6fded8f | 271 | /* And the built-in hashing mechanism worked as expected */ |
0cee70eb | 272 | cl_assert_equal_oid(&id1, &entry->id); |
f45ec1a0 | 273 | |
f6fded8f VM |
274 | /* Test access by path instead of index */ |
275 | cl_assert((entry = git_index_get_bypath(index, "test.txt", 0)) != NULL); | |
0cee70eb | 276 | cl_assert_equal_oid(&id1, &entry->id); |
f6fded8f VM |
277 | |
278 | git_index_free(index); | |
279 | git_repository_free(repo); | |
6c106eec BS |
280 | } |
281 | ||
a275fbc0 DP |
282 | void test_index_tests__add_frombuffer(void) |
283 | { | |
284 | git_index *index; | |
285 | git_repository *repo; | |
286 | git_index_entry entry; | |
287 | const git_index_entry *returned_entry; | |
288 | ||
289 | git_oid id1; | |
290 | git_blob *blob; | |
291 | ||
292 | const char *content = "hey there\n"; | |
293 | ||
294 | cl_set_cleanup(&cleanup_myrepo, NULL); | |
295 | ||
e579e0f7 | 296 | /* Initialize a new repository */ |
a275fbc0 DP |
297 | cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); |
298 | ||
299 | /* Ensure we're the only guy in the room */ | |
300 | cl_git_pass(git_repository_index(&index, repo)); | |
301 | cl_assert(git_index_entrycount(index) == 0); | |
302 | ||
303 | /* Store the expected hash of the file/blob | |
304 | * This has been generated by executing the following | |
305 | * $ echo "hey there" | git hash-object --stdin | |
306 | */ | |
307 | cl_git_pass(git_oid_fromstr(&id1, "a8233120f6ad708f843d861ce2b7228ec4e3dec6")); | |
308 | ||
309 | /* Add the new file to the index */ | |
310 | memset(&entry, 0x0, sizeof(git_index_entry)); | |
311 | entry.mode = GIT_FILEMODE_BLOB; | |
312 | entry.path = "test.txt"; | |
22a2d3d5 | 313 | cl_git_pass(git_index_add_from_buffer(index, &entry, |
a275fbc0 DP |
314 | content, strlen(content))); |
315 | ||
316 | /* Wow... it worked! */ | |
317 | cl_assert(git_index_entrycount(index) == 1); | |
318 | returned_entry = git_index_get_byindex(index, 0); | |
319 | ||
320 | /* And the built-in hashing mechanism worked as expected */ | |
321 | cl_assert_equal_oid(&id1, &returned_entry->id); | |
322 | /* And mode is the one asked */ | |
323 | cl_assert_equal_i(GIT_FILEMODE_BLOB, returned_entry->mode); | |
324 | ||
325 | /* Test access by path instead of index */ | |
326 | cl_assert((returned_entry = git_index_get_bypath(index, "test.txt", 0)) != NULL); | |
327 | cl_assert_equal_oid(&id1, &returned_entry->id); | |
328 | ||
329 | /* Test the blob is in the repository */ | |
330 | cl_git_pass(git_blob_lookup(&blob, repo, &id1)); | |
331 | cl_assert_equal_s( | |
332 | content, git_blob_rawcontent(blob)); | |
333 | git_blob_free(blob); | |
334 | ||
335 | git_index_free(index); | |
336 | git_repository_free(repo); | |
337 | } | |
338 | ||
ac3d33df JK |
339 | void test_index_tests__dirty_and_clean(void) |
340 | { | |
341 | git_repository *repo; | |
342 | git_index *index; | |
343 | git_index_entry entry = {{0}}; | |
344 | ||
345 | /* Index is not dirty after opening */ | |
346 | cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); | |
347 | cl_git_pass(git_repository_index(&index, repo)); | |
348 | ||
349 | cl_assert(git_index_entrycount(index) == 0); | |
350 | cl_assert(!git_index_is_dirty(index)); | |
351 | ||
352 | /* Index is dirty after adding an entry */ | |
353 | entry.mode = GIT_FILEMODE_BLOB; | |
354 | entry.path = "test.txt"; | |
22a2d3d5 | 355 | cl_git_pass(git_index_add_from_buffer(index, &entry, "Hi.\n", 4)); |
ac3d33df JK |
356 | cl_assert(git_index_entrycount(index) == 1); |
357 | cl_assert(git_index_is_dirty(index)); | |
358 | ||
359 | /* Index is not dirty after write */ | |
360 | cl_git_pass(git_index_write(index)); | |
361 | cl_assert(!git_index_is_dirty(index)); | |
362 | ||
363 | /* Index is dirty after removing an entry */ | |
364 | cl_git_pass(git_index_remove_bypath(index, "test.txt")); | |
365 | cl_assert(git_index_entrycount(index) == 0); | |
366 | cl_assert(git_index_is_dirty(index)); | |
367 | ||
368 | /* Index is not dirty after write */ | |
369 | cl_git_pass(git_index_write(index)); | |
370 | cl_assert(!git_index_is_dirty(index)); | |
371 | ||
372 | /* Index remains not dirty after read */ | |
373 | cl_git_pass(git_index_read(index, 0)); | |
374 | cl_assert(!git_index_is_dirty(index)); | |
375 | ||
376 | /* Index is dirty when we do an unforced read with dirty content */ | |
22a2d3d5 | 377 | cl_git_pass(git_index_add_from_buffer(index, &entry, "Hi.\n", 4)); |
ac3d33df JK |
378 | cl_assert(git_index_entrycount(index) == 1); |
379 | cl_assert(git_index_is_dirty(index)); | |
380 | ||
381 | cl_git_pass(git_index_read(index, 0)); | |
382 | cl_assert(git_index_is_dirty(index)); | |
383 | ||
384 | /* Index is clean when we force a read with dirty content */ | |
385 | cl_git_pass(git_index_read(index, 1)); | |
386 | cl_assert(!git_index_is_dirty(index)); | |
387 | ||
388 | git_index_free(index); | |
389 | git_repository_free(repo); | |
390 | } | |
391 | ||
392 | void test_index_tests__dirty_fails_optionally(void) | |
393 | { | |
394 | git_repository *repo; | |
395 | git_index *index; | |
396 | git_index_entry entry = {{0}}; | |
397 | ||
398 | /* Index is not dirty after opening */ | |
399 | repo = cl_git_sandbox_init("testrepo"); | |
400 | cl_git_pass(git_repository_index(&index, repo)); | |
401 | ||
402 | /* Index is dirty after adding an entry */ | |
403 | entry.mode = GIT_FILEMODE_BLOB; | |
404 | entry.path = "test.txt"; | |
22a2d3d5 | 405 | cl_git_pass(git_index_add_from_buffer(index, &entry, "Hi.\n", 4)); |
ac3d33df JK |
406 | cl_assert(git_index_is_dirty(index)); |
407 | ||
408 | cl_git_pass(git_checkout_head(repo, NULL)); | |
409 | ||
410 | /* Index is dirty (again) after adding an entry */ | |
411 | entry.mode = GIT_FILEMODE_BLOB; | |
412 | entry.path = "test.txt"; | |
22a2d3d5 | 413 | cl_git_pass(git_index_add_from_buffer(index, &entry, "Hi.\n", 4)); |
ac3d33df JK |
414 | cl_assert(git_index_is_dirty(index)); |
415 | ||
416 | cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_UNSAVED_INDEX_SAFETY, 1)); | |
417 | cl_git_fail_with(GIT_EINDEXDIRTY, git_checkout_head(repo, NULL)); | |
418 | ||
419 | git_index_free(index); | |
420 | cl_git_sandbox_cleanup(); | |
421 | } | |
422 | ||
a275fbc0 DP |
423 | void test_index_tests__add_frombuffer_reset_entry(void) |
424 | { | |
425 | git_index *index; | |
426 | git_repository *repo; | |
427 | git_index_entry entry; | |
428 | const git_index_entry *returned_entry; | |
429 | git_filebuf file = GIT_FILEBUF_INIT; | |
430 | ||
431 | git_oid id1; | |
432 | git_blob *blob; | |
433 | const char *old_content = "here\n"; | |
434 | const char *content = "hey there\n"; | |
435 | ||
436 | cl_set_cleanup(&cleanup_myrepo, NULL); | |
437 | ||
e579e0f7 | 438 | /* Initialize a new repository */ |
a275fbc0 DP |
439 | cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); |
440 | cl_git_pass(git_repository_index(&index, repo)); | |
441 | cl_git_pass(git_futils_mkpath2file("myrepo/test.txt", 0777)); | |
442 | cl_git_pass(git_filebuf_open(&file, "myrepo/test.txt", 0, 0666)); | |
443 | cl_git_pass(git_filebuf_write(&file, old_content, strlen(old_content))); | |
444 | cl_git_pass(git_filebuf_commit(&file)); | |
445 | ||
446 | /* Store the expected hash of the file/blob | |
447 | * This has been generated by executing the following | |
448 | * $ echo "hey there" | git hash-object --stdin | |
449 | */ | |
450 | cl_git_pass(git_oid_fromstr(&id1, "a8233120f6ad708f843d861ce2b7228ec4e3dec6")); | |
451 | ||
452 | cl_git_pass(git_index_add_bypath(index, "test.txt")); | |
453 | ||
454 | /* Add the new file to the index */ | |
455 | memset(&entry, 0x0, sizeof(git_index_entry)); | |
456 | entry.mode = GIT_FILEMODE_BLOB; | |
457 | entry.path = "test.txt"; | |
22a2d3d5 | 458 | cl_git_pass(git_index_add_from_buffer(index, &entry, |
a275fbc0 DP |
459 | content, strlen(content))); |
460 | ||
461 | /* Wow... it worked! */ | |
462 | cl_assert(git_index_entrycount(index) == 1); | |
463 | returned_entry = git_index_get_byindex(index, 0); | |
464 | ||
465 | /* And the built-in hashing mechanism worked as expected */ | |
466 | cl_assert_equal_oid(&id1, &returned_entry->id); | |
467 | /* And mode is the one asked */ | |
468 | cl_assert_equal_i(GIT_FILEMODE_BLOB, returned_entry->mode); | |
469 | ||
470 | /* Test access by path instead of index */ | |
471 | cl_assert((returned_entry = git_index_get_bypath(index, "test.txt", 0)) != NULL); | |
472 | cl_assert_equal_oid(&id1, &returned_entry->id); | |
473 | cl_assert_equal_i(0, returned_entry->dev); | |
474 | cl_assert_equal_i(0, returned_entry->ino); | |
475 | cl_assert_equal_i(0, returned_entry->uid); | |
476 | cl_assert_equal_i(0, returned_entry->uid); | |
477 | cl_assert_equal_i(10, returned_entry->file_size); | |
478 | ||
479 | /* Test the blob is in the repository */ | |
480 | cl_git_pass(git_blob_lookup(&blob, repo, &id1)); | |
481 | cl_assert_equal_s(content, git_blob_rawcontent(blob)); | |
482 | git_blob_free(blob); | |
483 | ||
484 | git_index_free(index); | |
485 | git_repository_free(repo); | |
486 | } | |
487 | ||
1098cfae RB |
488 | static void cleanup_1397(void *opaque) |
489 | { | |
490 | GIT_UNUSED(opaque); | |
491 | cl_git_sandbox_cleanup(); | |
492 | } | |
493 | ||
b8acb775 SS |
494 | void test_index_tests__add_issue_1397(void) |
495 | { | |
496 | git_index *index; | |
b8acb775 SS |
497 | git_repository *repo; |
498 | const git_index_entry *entry; | |
499 | git_oid id1; | |
500 | ||
1098cfae | 501 | cl_set_cleanup(&cleanup_1397, NULL); |
b8acb775 SS |
502 | |
503 | repo = cl_git_sandbox_init("issue_1397"); | |
504 | ||
1098cfae | 505 | cl_repo_set_bool(repo, "core.autocrlf", true); |
b8acb775 SS |
506 | |
507 | /* Ensure we're the only guy in the room */ | |
508 | cl_git_pass(git_repository_index(&index, repo)); | |
509 | ||
510 | /* Store the expected hash of the file/blob | |
511 | * This has been generated by executing the following | |
512 | * $ git hash-object crlf_file.txt | |
513 | */ | |
514 | cl_git_pass(git_oid_fromstr(&id1, "8312e0889a9cbab77c732b6bc39b51a683e3a318")); | |
515 | ||
516 | /* Make sure the initial SHA-1 is correct */ | |
517 | cl_assert((entry = git_index_get_bypath(index, "crlf_file.txt", 0)) != NULL); | |
0cee70eb | 518 | cl_assert_equal_oid(&id1, &entry->id); |
b8acb775 SS |
519 | |
520 | /* Update the index */ | |
521 | cl_git_pass(git_index_add_bypath(index, "crlf_file.txt")); | |
522 | ||
523 | /* Check the new SHA-1 */ | |
524 | cl_assert((entry = git_index_get_bypath(index, "crlf_file.txt", 0)) != NULL); | |
0cee70eb | 525 | cl_assert_equal_oid(&id1, &entry->id); |
b8acb775 SS |
526 | |
527 | git_index_free(index); | |
b8acb775 SS |
528 | } |
529 | ||
25743bd7 | 530 | void test_index_tests__add_bypath_to_a_bare_repository_returns_EBAREPO(void) |
33f95a9b | 531 | { |
532 | git_repository *bare_repo; | |
533 | git_index *index; | |
534 | ||
535 | cl_git_pass(git_repository_open(&bare_repo, cl_fixture("testrepo.git"))); | |
536 | cl_git_pass(git_repository_index(&index, bare_repo)); | |
537 | ||
25743bd7 | 538 | cl_assert_equal_i(GIT_EBAREREPO, git_index_add_bypath(index, "test.txt")); |
33f95a9b | 539 | |
540 | git_index_free(index); | |
541 | git_repository_free(bare_repo); | |
542 | } | |
1876360f | 543 | |
b6832cbf | 544 | static void assert_add_bypath_fails(git_repository *repo, const char *fn) |
0d388adc VM |
545 | { |
546 | git_index *index; | |
e579e0f7 | 547 | git_str path = GIT_STR_INIT; |
0d388adc VM |
548 | |
549 | cl_git_pass(git_repository_index(&index, repo)); | |
550 | cl_assert(git_index_entrycount(index) == 0); | |
551 | ||
e579e0f7 | 552 | git_str_joinpath(&path, "./invalid", fn); |
0d388adc VM |
553 | |
554 | cl_git_mkfile(path.ptr, NULL); | |
555 | cl_git_fail(git_index_add_bypath(index, fn)); | |
556 | cl_must_pass(p_unlink(path.ptr)); | |
557 | ||
558 | cl_assert(git_index_entrycount(index) == 0); | |
559 | ||
e579e0f7 | 560 | git_str_dispose(&path); |
0d388adc VM |
561 | git_index_free(index); |
562 | } | |
563 | ||
1876360f | 564 | /* Test that writing an invalid filename fails */ |
b6832cbf | 565 | void test_index_tests__cannot_add_invalid_filename(void) |
1876360f SG |
566 | { |
567 | git_repository *repo; | |
0d388adc | 568 | |
22a2d3d5 | 569 | cl_must_pass(p_mkdir("invalid", 0700)); |
0d388adc VM |
570 | cl_git_pass(git_repository_init(&repo, "./invalid", 0)); |
571 | cl_must_pass(p_mkdir("./invalid/subdir", 0777)); | |
572 | ||
c679bf42 | 573 | /* cl_git_mkfile() needs the dir to exist */ |
e579e0f7 | 574 | if (!git_fs_path_exists("./invalid/.GIT")) |
28428318 | 575 | cl_must_pass(p_mkdir("./invalid/.GIT", 0777)); |
e579e0f7 | 576 | if (!git_fs_path_exists("./invalid/.GiT")) |
28428318 | 577 | cl_must_pass(p_mkdir("./invalid/.GiT", 0777)); |
c679bf42 | 578 | |
b6832cbf UG |
579 | assert_add_bypath_fails(repo, ".git/hello"); |
580 | assert_add_bypath_fails(repo, ".GIT/hello"); | |
581 | assert_add_bypath_fails(repo, ".GiT/hello"); | |
582 | assert_add_bypath_fails(repo, "./.git/hello"); | |
583 | assert_add_bypath_fails(repo, "./foo"); | |
584 | assert_add_bypath_fails(repo, "./bar"); | |
585 | assert_add_bypath_fails(repo, "subdir/../bar"); | |
586 | ||
587 | git_repository_free(repo); | |
588 | ||
589 | cl_fixture_cleanup("invalid"); | |
590 | } | |
591 | ||
592 | static void assert_add_fails(git_repository *repo, const char *fn) | |
593 | { | |
594 | git_index *index; | |
e579e0f7 | 595 | git_str path = GIT_STR_INIT; |
b6832cbf UG |
596 | git_index_entry entry = {{0}}; |
597 | ||
598 | cl_git_pass(git_repository_index(&index, repo)); | |
599 | cl_assert(git_index_entrycount(index) == 0); | |
600 | ||
601 | entry.path = fn; | |
602 | entry.mode = GIT_FILEMODE_BLOB; | |
603 | cl_git_pass(git_oid_fromstr(&entry.id, "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391")); | |
604 | ||
605 | cl_git_fail(git_index_add(index, &entry)); | |
606 | ||
607 | cl_assert(git_index_entrycount(index) == 0); | |
608 | ||
e579e0f7 | 609 | git_str_dispose(&path); |
b6832cbf UG |
610 | git_index_free(index); |
611 | } | |
612 | ||
613 | /* | |
614 | * Test that writing an invalid filename fails on filesystem | |
615 | * specific protected names | |
616 | */ | |
617 | void test_index_tests__cannot_add_protected_invalid_filename(void) | |
618 | { | |
619 | git_repository *repo; | |
620 | git_index *index; | |
621 | ||
622 | cl_must_pass(p_mkdir("invalid", 0700)); | |
623 | ||
624 | cl_git_pass(git_repository_init(&repo, "./invalid", 0)); | |
625 | ||
626 | /* add a file to the repository so we can reference it later */ | |
627 | cl_git_pass(git_repository_index(&index, repo)); | |
628 | cl_git_mkfile("invalid/dummy.txt", ""); | |
629 | cl_git_pass(git_index_add_bypath(index, "dummy.txt")); | |
630 | cl_must_pass(p_unlink("invalid/dummy.txt")); | |
631 | cl_git_pass(git_index_remove_bypath(index, "dummy.txt")); | |
632 | git_index_free(index); | |
633 | ||
634 | cl_repo_set_bool(repo, "core.protectHFS", true); | |
635 | cl_repo_set_bool(repo, "core.protectNTFS", true); | |
636 | ||
637 | assert_add_fails(repo, ".git./hello"); | |
638 | assert_add_fails(repo, ".git\xe2\x80\xad/hello"); | |
639 | assert_add_fails(repo, "git~1/hello"); | |
640 | assert_add_fails(repo, ".git\xe2\x81\xaf/hello"); | |
641 | assert_add_fails(repo, ".git::$INDEX_ALLOCATION/dummy-file"); | |
0d388adc VM |
642 | |
643 | git_repository_free(repo); | |
644 | ||
645 | cl_fixture_cleanup("invalid"); | |
646 | } | |
647 | ||
648 | static void replace_char(char *str, char in, char out) | |
649 | { | |
650 | char *c = str; | |
651 | ||
652 | while (*c++) | |
653 | if (*c == in) | |
654 | *c = out; | |
655 | } | |
656 | ||
b6832cbf | 657 | static void assert_write_fails(git_repository *repo, const char *fn_orig) |
0d388adc | 658 | { |
1876360f SG |
659 | git_index *index; |
660 | git_oid expected; | |
0d388adc | 661 | const git_index_entry *entry; |
e579e0f7 | 662 | git_str path = GIT_STR_INIT; |
0d388adc | 663 | char *fn; |
1876360f | 664 | |
1876360f | 665 | cl_git_pass(git_repository_index(&index, repo)); |
1876360f SG |
666 | cl_assert(git_index_entrycount(index) == 0); |
667 | ||
0d388adc VM |
668 | /* |
669 | * Sneak a valid path into the index, we'll update it | |
670 | * to an invalid path when we try to write the index. | |
671 | */ | |
672 | fn = git__strdup(fn_orig); | |
673 | replace_char(fn, '/', '_'); | |
b6832cbf | 674 | replace_char(fn, ':', '!'); |
0d388adc | 675 | |
e579e0f7 | 676 | git_str_joinpath(&path, "./invalid", fn); |
0d388adc VM |
677 | |
678 | cl_git_mkfile(path.ptr, NULL); | |
679 | ||
680 | cl_git_pass(git_index_add_bypath(index, fn)); | |
681 | ||
682 | cl_assert(entry = git_index_get_bypath(index, fn, 0)); | |
1876360f | 683 | |
0d388adc VM |
684 | /* kids, don't try this at home */ |
685 | replace_char((char *)entry->path, '_', '/'); | |
b6832cbf | 686 | replace_char((char *)entry->path, '!', ':'); |
1876360f SG |
687 | |
688 | /* write-tree */ | |
689 | cl_git_fail(git_index_write_tree(&expected, index)); | |
690 | ||
0d388adc VM |
691 | p_unlink(path.ptr); |
692 | ||
693 | cl_git_pass(git_index_remove_all(index, NULL, NULL, NULL)); | |
e579e0f7 | 694 | git_str_dispose(&path); |
1876360f | 695 | git_index_free(index); |
0d388adc VM |
696 | git__free(fn); |
697 | } | |
698 | ||
ac3d33df JK |
699 | void test_index_tests__write_tree_invalid_unowned_index(void) |
700 | { | |
701 | git_index *idx; | |
702 | git_repository *repo; | |
703 | git_index_entry entry = {{0}}; | |
704 | git_oid tree_id; | |
705 | ||
706 | cl_git_pass(git_index_new(&idx)); | |
707 | ||
708 | cl_git_pass(git_oid_fromstr(&entry.id, "8312e0a89a9cbab77c732b6bc39b51a783e3a318")); | |
709 | entry.path = "foo"; | |
710 | entry.mode = GIT_FILEMODE_BLOB; | |
711 | cl_git_pass(git_index_add(idx, &entry)); | |
712 | ||
713 | cl_git_pass(git_repository_init(&repo, "./invalid-id", 0)); | |
714 | ||
715 | cl_git_fail(git_index_write_tree_to(&tree_id, idx, repo)); | |
716 | ||
717 | git_index_free(idx); | |
718 | git_repository_free(repo); | |
719 | ||
720 | cl_fixture_cleanup("invalid-id"); | |
721 | } | |
722 | ||
0d388adc VM |
723 | /* Test that writing an invalid filename fails */ |
724 | void test_index_tests__write_invalid_filename(void) | |
725 | { | |
726 | git_repository *repo; | |
727 | ||
728 | p_mkdir("invalid", 0700); | |
729 | ||
730 | cl_git_pass(git_repository_init(&repo, "./invalid", 0)); | |
731 | ||
b6832cbf UG |
732 | assert_write_fails(repo, ".git/hello"); |
733 | assert_write_fails(repo, ".GIT/hello"); | |
734 | assert_write_fails(repo, ".GiT/hello"); | |
735 | assert_write_fails(repo, "./.git/hello"); | |
736 | assert_write_fails(repo, "./foo"); | |
737 | assert_write_fails(repo, "./bar"); | |
738 | assert_write_fails(repo, "foo/../bar"); | |
0d388adc | 739 | |
1876360f SG |
740 | git_repository_free(repo); |
741 | ||
0d388adc | 742 | cl_fixture_cleanup("invalid"); |
1876360f | 743 | } |
7fc00435 | 744 | |
dce7b1a4 ET |
745 | void test_index_tests__honors_protect_filesystems(void) |
746 | { | |
747 | git_repository *repo; | |
748 | ||
749 | p_mkdir("invalid", 0700); | |
750 | ||
751 | cl_git_pass(git_repository_init(&repo, "./invalid", 0)); | |
752 | ||
753 | cl_repo_set_bool(repo, "core.protectHFS", true); | |
754 | cl_repo_set_bool(repo, "core.protectNTFS", true); | |
755 | ||
b6832cbf UG |
756 | assert_write_fails(repo, ".git./hello"); |
757 | assert_write_fails(repo, ".git\xe2\x80\xad/hello"); | |
758 | assert_write_fails(repo, "git~1/hello"); | |
759 | assert_write_fails(repo, ".git\xe2\x81\xaf/hello"); | |
760 | assert_write_fails(repo, ".git::$INDEX_ALLOCATION/dummy-file"); | |
761 | ||
762 | git_repository_free(repo); | |
763 | ||
764 | cl_fixture_cleanup("invalid"); | |
765 | } | |
766 | ||
767 | void test_index_tests__protectntfs_on_by_default(void) | |
768 | { | |
769 | git_repository *repo; | |
770 | ||
771 | p_mkdir("invalid", 0700); | |
772 | ||
773 | cl_git_pass(git_repository_init(&repo, "./invalid", 0)); | |
774 | assert_write_fails(repo, ".git./hello"); | |
775 | assert_write_fails(repo, "git~1/hello"); | |
dce7b1a4 ET |
776 | |
777 | git_repository_free(repo); | |
778 | ||
779 | cl_fixture_cleanup("invalid"); | |
780 | } | |
781 | ||
b6832cbf UG |
782 | void test_index_tests__can_disable_protectntfs(void) |
783 | { | |
784 | git_repository *repo; | |
785 | git_index *index; | |
786 | ||
787 | cl_must_pass(p_mkdir("valid", 0700)); | |
788 | cl_git_rewritefile("valid/git~1", "steal the shortname"); | |
789 | ||
790 | cl_git_pass(git_repository_init(&repo, "./valid", 0)); | |
791 | cl_git_pass(git_repository_index(&index, repo)); | |
792 | cl_repo_set_bool(repo, "core.protectNTFS", false); | |
793 | ||
794 | cl_git_pass(git_index_add_bypath(index, "git~1")); | |
795 | ||
796 | git_index_free(index); | |
797 | git_repository_free(repo); | |
798 | ||
799 | cl_fixture_cleanup("valid"); | |
800 | } | |
801 | ||
7fc00435 RB |
802 | void test_index_tests__remove_entry(void) |
803 | { | |
804 | git_repository *repo; | |
805 | git_index *index; | |
806 | ||
807 | p_mkdir("index_test", 0770); | |
808 | ||
809 | cl_git_pass(git_repository_init(&repo, "index_test", 0)); | |
810 | cl_git_pass(git_repository_index(&index, repo)); | |
811 | cl_assert(git_index_entrycount(index) == 0); | |
812 | ||
813 | cl_git_mkfile("index_test/hello", NULL); | |
25743bd7 | 814 | cl_git_pass(git_index_add_bypath(index, "hello")); |
7fc00435 RB |
815 | cl_git_pass(git_index_write(index)); |
816 | ||
8e5a8ef8 | 817 | cl_git_pass(git_index_read(index, true)); /* reload */ |
7fc00435 RB |
818 | cl_assert(git_index_entrycount(index) == 1); |
819 | cl_assert(git_index_get_bypath(index, "hello", 0) != NULL); | |
820 | ||
821 | cl_git_pass(git_index_remove(index, "hello", 0)); | |
822 | cl_git_pass(git_index_write(index)); | |
823 | ||
8e5a8ef8 | 824 | cl_git_pass(git_index_read(index, true)); /* reload */ |
7fc00435 RB |
825 | cl_assert(git_index_entrycount(index) == 0); |
826 | cl_assert(git_index_get_bypath(index, "hello", 0) == NULL); | |
827 | ||
828 | git_index_free(index); | |
829 | git_repository_free(repo); | |
830 | cl_fixture_cleanup("index_test"); | |
831 | } | |
832 | ||
833 | void test_index_tests__remove_directory(void) | |
834 | { | |
835 | git_repository *repo; | |
836 | git_index *index; | |
837 | ||
838 | p_mkdir("index_test", 0770); | |
839 | ||
840 | cl_git_pass(git_repository_init(&repo, "index_test", 0)); | |
841 | cl_git_pass(git_repository_index(&index, repo)); | |
842 | cl_assert_equal_i(0, (int)git_index_entrycount(index)); | |
843 | ||
844 | p_mkdir("index_test/a", 0770); | |
845 | cl_git_mkfile("index_test/a/1.txt", NULL); | |
846 | cl_git_mkfile("index_test/a/2.txt", NULL); | |
847 | cl_git_mkfile("index_test/a/3.txt", NULL); | |
848 | cl_git_mkfile("index_test/b.txt", NULL); | |
849 | ||
25743bd7 ET |
850 | cl_git_pass(git_index_add_bypath(index, "a/1.txt")); |
851 | cl_git_pass(git_index_add_bypath(index, "a/2.txt")); | |
852 | cl_git_pass(git_index_add_bypath(index, "a/3.txt")); | |
853 | cl_git_pass(git_index_add_bypath(index, "b.txt")); | |
7fc00435 RB |
854 | cl_git_pass(git_index_write(index)); |
855 | ||
8e5a8ef8 | 856 | cl_git_pass(git_index_read(index, true)); /* reload */ |
7fc00435 RB |
857 | cl_assert_equal_i(4, (int)git_index_entrycount(index)); |
858 | cl_assert(git_index_get_bypath(index, "a/1.txt", 0) != NULL); | |
859 | cl_assert(git_index_get_bypath(index, "a/2.txt", 0) != NULL); | |
860 | cl_assert(git_index_get_bypath(index, "b.txt", 0) != NULL); | |
861 | ||
862 | cl_git_pass(git_index_remove(index, "a/1.txt", 0)); | |
863 | cl_git_pass(git_index_write(index)); | |
864 | ||
8e5a8ef8 | 865 | cl_git_pass(git_index_read(index, true)); /* reload */ |
7fc00435 RB |
866 | cl_assert_equal_i(3, (int)git_index_entrycount(index)); |
867 | cl_assert(git_index_get_bypath(index, "a/1.txt", 0) == NULL); | |
868 | cl_assert(git_index_get_bypath(index, "a/2.txt", 0) != NULL); | |
869 | cl_assert(git_index_get_bypath(index, "b.txt", 0) != NULL); | |
870 | ||
871 | cl_git_pass(git_index_remove_directory(index, "a", 0)); | |
872 | cl_git_pass(git_index_write(index)); | |
873 | ||
8e5a8ef8 | 874 | cl_git_pass(git_index_read(index, true)); /* reload */ |
7fc00435 RB |
875 | cl_assert_equal_i(1, (int)git_index_entrycount(index)); |
876 | cl_assert(git_index_get_bypath(index, "a/1.txt", 0) == NULL); | |
877 | cl_assert(git_index_get_bypath(index, "a/2.txt", 0) == NULL); | |
878 | cl_assert(git_index_get_bypath(index, "b.txt", 0) != NULL); | |
879 | ||
880 | git_index_free(index); | |
881 | git_repository_free(repo); | |
882 | cl_fixture_cleanup("index_test"); | |
883 | } | |
1540b199 ET |
884 | |
885 | void test_index_tests__preserves_case(void) | |
886 | { | |
887 | git_repository *repo; | |
888 | git_index *index; | |
889 | const git_index_entry *entry; | |
fb03a223 | 890 | int index_caps; |
1540b199 ET |
891 | |
892 | cl_set_cleanup(&cleanup_myrepo, NULL); | |
893 | ||
894 | cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); | |
895 | cl_git_pass(git_repository_index(&index, repo)); | |
896 | ||
fb03a223 RB |
897 | index_caps = git_index_caps(index); |
898 | ||
1540b199 ET |
899 | cl_git_rewritefile("myrepo/test.txt", "hey there\n"); |
900 | cl_git_pass(git_index_add_bypath(index, "test.txt")); | |
901 | ||
902 | cl_git_pass(p_rename("myrepo/test.txt", "myrepo/TEST.txt")); | |
903 | cl_git_rewritefile("myrepo/TEST.txt", "hello again\n"); | |
904 | cl_git_pass(git_index_add_bypath(index, "TEST.txt")); | |
905 | ||
ac3d33df | 906 | if (index_caps & GIT_INDEX_CAPABILITY_IGNORE_CASE) |
fb03a223 RB |
907 | cl_assert_equal_i(1, (int)git_index_entrycount(index)); |
908 | else | |
909 | cl_assert_equal_i(2, (int)git_index_entrycount(index)); | |
1540b199 ET |
910 | |
911 | /* Test access by path instead of index */ | |
912 | cl_assert((entry = git_index_get_bypath(index, "test.txt", 0)) != NULL); | |
1540b199 ET |
913 | /* The path should *not* have changed without an explicit remove */ |
914 | cl_assert(git__strcmp(entry->path, "test.txt") == 0); | |
915 | ||
fb03a223 | 916 | cl_assert((entry = git_index_get_bypath(index, "TEST.txt", 0)) != NULL); |
ac3d33df | 917 | if (index_caps & GIT_INDEX_CAPABILITY_IGNORE_CASE) |
fb03a223 RB |
918 | /* The path should *not* have changed without an explicit remove */ |
919 | cl_assert(git__strcmp(entry->path, "test.txt") == 0); | |
920 | else | |
921 | cl_assert(git__strcmp(entry->path, "TEST.txt") == 0); | |
922 | ||
1540b199 ET |
923 | git_index_free(index); |
924 | git_repository_free(repo); | |
925 | } | |
926 | ||
3d276874 CMN |
927 | void test_index_tests__elocked(void) |
928 | { | |
929 | git_repository *repo; | |
930 | git_index *index; | |
931 | git_filebuf file = GIT_FILEBUF_INIT; | |
932 | const git_error *err; | |
933 | int error; | |
934 | ||
935 | cl_set_cleanup(&cleanup_myrepo, NULL); | |
936 | ||
937 | cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); | |
938 | cl_git_pass(git_repository_index(&index, repo)); | |
939 | ||
940 | /* Lock the index file so we fail to lock it */ | |
1d3a8aeb | 941 | cl_git_pass(git_filebuf_open(&file, index->index_file_path, 0, 0666)); |
3d276874 CMN |
942 | error = git_index_write(index); |
943 | cl_assert_equal_i(GIT_ELOCKED, error); | |
944 | ||
ac3d33df JK |
945 | err = git_error_last(); |
946 | cl_assert_equal_i(err->klass, GIT_ERROR_INDEX); | |
3d276874 CMN |
947 | |
948 | git_filebuf_cleanup(&file); | |
949 | git_index_free(index); | |
950 | git_repository_free(repo); | |
951 | } | |
da7b78fa | 952 | |
953 | void test_index_tests__reload_from_disk(void) | |
954 | { | |
955 | git_repository *repo; | |
956 | git_index *read_index; | |
957 | git_index *write_index; | |
958 | ||
959 | cl_set_cleanup(&cleanup_myrepo, NULL); | |
960 | ||
ac2fba0e | 961 | cl_git_pass(git_futils_mkdir("./myrepo", 0777, GIT_MKDIR_PATH)); |
da7b78fa | 962 | cl_git_mkfile("./myrepo/a.txt", "a\n"); |
963 | cl_git_mkfile("./myrepo/b.txt", "b\n"); | |
964 | ||
965 | cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); | |
966 | cl_git_pass(git_repository_index(&write_index, repo)); | |
967 | cl_assert_equal_i(false, write_index->on_disk); | |
968 | ||
969 | cl_git_pass(git_index_open(&read_index, write_index->index_file_path)); | |
970 | cl_assert_equal_i(false, read_index->on_disk); | |
971 | ||
b874629b | 972 | /* Stage two new files against the write_index */ |
da7b78fa | 973 | cl_git_pass(git_index_add_bypath(write_index, "a.txt")); |
974 | cl_git_pass(git_index_add_bypath(write_index, "b.txt")); | |
975 | ||
976 | cl_assert_equal_sz(2, git_index_entrycount(write_index)); | |
977 | ||
978 | /* Persist the index changes to disk */ | |
979 | cl_git_pass(git_index_write(write_index)); | |
980 | cl_assert_equal_i(true, write_index->on_disk); | |
981 | ||
982 | /* Sync the changes back into the read_index */ | |
983 | cl_assert_equal_sz(0, git_index_entrycount(read_index)); | |
984 | ||
8e5a8ef8 | 985 | cl_git_pass(git_index_read(read_index, true)); |
da7b78fa | 986 | cl_assert_equal_i(true, read_index->on_disk); |
987 | ||
988 | cl_assert_equal_sz(2, git_index_entrycount(read_index)); | |
989 | ||
990 | /* Remove the index file from the filesystem */ | |
991 | cl_git_pass(p_unlink(write_index->index_file_path)); | |
992 | ||
993 | /* Sync the changes back into the read_index */ | |
8e5a8ef8 | 994 | cl_git_pass(git_index_read(read_index, true)); |
da7b78fa | 995 | cl_assert_equal_i(false, read_index->on_disk); |
996 | cl_assert_equal_sz(0, git_index_entrycount(read_index)); | |
997 | ||
998 | git_index_free(read_index); | |
999 | git_index_free(write_index); | |
1000 | git_repository_free(repo); | |
1001 | } | |
3d523345 | 1002 | |
1003 | void test_index_tests__corrupted_extension(void) | |
1004 | { | |
3d523345 | 1005 | git_index *index; |
1006 | ||
1007 | cl_git_fail_with(git_index_open(&index, TEST_INDEXBAD_PATH), GIT_ERROR); | |
1008 | } | |
43709ca8 | 1009 | |
43709ca8 RB |
1010 | void test_index_tests__reload_while_ignoring_case(void) |
1011 | { | |
1012 | git_index *index; | |
1013 | unsigned int caps; | |
1014 | ||
1015 | cl_git_pass(git_index_open(&index, TEST_INDEX_PATH)); | |
c67fd4c9 | 1016 | cl_git_pass(git_vector_verify_sorted(&index->entries)); |
43709ca8 RB |
1017 | |
1018 | caps = git_index_caps(index); | |
ac3d33df | 1019 | cl_git_pass(git_index_set_caps(index, caps &= ~GIT_INDEX_CAPABILITY_IGNORE_CASE)); |
43709ca8 | 1020 | cl_git_pass(git_index_read(index, true)); |
c67fd4c9 | 1021 | cl_git_pass(git_vector_verify_sorted(&index->entries)); |
c232d6c3 CMN |
1022 | cl_assert(git_index_get_bypath(index, ".HEADER", 0)); |
1023 | cl_assert_equal_p(NULL, git_index_get_bypath(index, ".header", 0)); | |
43709ca8 | 1024 | |
ac3d33df | 1025 | cl_git_pass(git_index_set_caps(index, caps | GIT_INDEX_CAPABILITY_IGNORE_CASE)); |
43709ca8 | 1026 | cl_git_pass(git_index_read(index, true)); |
c67fd4c9 | 1027 | cl_git_pass(git_vector_verify_sorted(&index->entries)); |
c232d6c3 CMN |
1028 | cl_assert(git_index_get_bypath(index, ".HEADER", 0)); |
1029 | cl_assert(git_index_get_bypath(index, ".header", 0)); | |
1030 | ||
1031 | git_index_free(index); | |
1032 | } | |
1033 | ||
1034 | void test_index_tests__change_icase_on_instance(void) | |
1035 | { | |
1036 | git_index *index; | |
1037 | unsigned int caps; | |
1038 | const git_index_entry *e; | |
1039 | ||
1040 | cl_git_pass(git_index_open(&index, TEST_INDEX_PATH)); | |
1041 | cl_git_pass(git_vector_verify_sorted(&index->entries)); | |
1042 | ||
1043 | caps = git_index_caps(index); | |
ac3d33df | 1044 | cl_git_pass(git_index_set_caps(index, caps &= ~GIT_INDEX_CAPABILITY_IGNORE_CASE)); |
c232d6c3 CMN |
1045 | cl_assert_equal_i(false, index->ignore_case); |
1046 | cl_git_pass(git_vector_verify_sorted(&index->entries)); | |
1047 | cl_assert(e = git_index_get_bypath(index, "src/common.h", 0)); | |
1048 | cl_assert_equal_p(NULL, e = git_index_get_bypath(index, "SRC/Common.h", 0)); | |
1049 | cl_assert(e = git_index_get_bypath(index, "COPYING", 0)); | |
1050 | cl_assert_equal_p(NULL, e = git_index_get_bypath(index, "copying", 0)); | |
1051 | ||
ac3d33df | 1052 | cl_git_pass(git_index_set_caps(index, caps | GIT_INDEX_CAPABILITY_IGNORE_CASE)); |
c232d6c3 CMN |
1053 | cl_assert_equal_i(true, index->ignore_case); |
1054 | cl_git_pass(git_vector_verify_sorted(&index->entries)); | |
1055 | cl_assert(e = git_index_get_bypath(index, "COPYING", 0)); | |
1056 | cl_assert_equal_s("COPYING", e->path); | |
1057 | cl_assert(e = git_index_get_bypath(index, "copying", 0)); | |
1058 | cl_assert_equal_s("COPYING", e->path); | |
43709ca8 RB |
1059 | |
1060 | git_index_free(index); | |
1061 | } | |
55798fd1 ET |
1062 | |
1063 | void test_index_tests__can_lock_index(void) | |
1064 | { | |
eae0bfdc | 1065 | git_repository *repo; |
55798fd1 ET |
1066 | git_index *index; |
1067 | git_indexwriter one = GIT_INDEXWRITER_INIT, | |
1068 | two = GIT_INDEXWRITER_INIT; | |
1069 | ||
eae0bfdc PP |
1070 | repo = cl_git_sandbox_init("testrepo.git"); |
1071 | ||
1072 | cl_git_pass(git_repository_index(&index, repo)); | |
55798fd1 ET |
1073 | cl_git_pass(git_indexwriter_init(&one, index)); |
1074 | ||
1075 | cl_git_fail_with(GIT_ELOCKED, git_indexwriter_init(&two, index)); | |
1076 | cl_git_fail_with(GIT_ELOCKED, git_index_write(index)); | |
1077 | ||
1078 | cl_git_pass(git_indexwriter_commit(&one)); | |
1079 | ||
1080 | cl_git_pass(git_index_write(index)); | |
1081 | ||
1082 | git_indexwriter_cleanup(&one); | |
1083 | git_indexwriter_cleanup(&two); | |
1084 | git_index_free(index); | |
eae0bfdc | 1085 | cl_git_sandbox_cleanup(); |
55798fd1 | 1086 | } |
ac3d33df JK |
1087 | |
1088 | void test_index_tests__can_iterate(void) | |
1089 | { | |
1090 | git_index *index; | |
1091 | git_index_iterator *iterator; | |
1092 | const git_index_entry *entry; | |
1093 | size_t i, iterator_idx = 0, found = 0; | |
1094 | int ret; | |
1095 | ||
1096 | cl_git_pass(git_index_open(&index, TEST_INDEX_PATH)); | |
1097 | cl_git_pass(git_index_iterator_new(&iterator, index)); | |
1098 | ||
1099 | cl_assert(git_vector_is_sorted(&iterator->snap)); | |
1100 | ||
1101 | for (i = 0; i < ARRAY_SIZE(test_entries); i++) { | |
1102 | /* Advance iterator to next test entry index */ | |
1103 | do { | |
1104 | ret = git_index_iterator_next(&entry, iterator); | |
1105 | ||
1106 | if (ret == GIT_ITEROVER) | |
1107 | cl_fail("iterator did not contain all test entries"); | |
1108 | ||
1109 | cl_git_pass(ret); | |
1110 | } while (iterator_idx++ < test_entries[i].index); | |
1111 | ||
1112 | cl_assert_equal_s(entry->path, test_entries[i].path); | |
1113 | cl_assert_equal_i(entry->mtime.seconds, test_entries[i].mtime); | |
1114 | cl_assert_equal_i(entry->file_size, test_entries[i].file_size); | |
1115 | found++; | |
1116 | } | |
1117 | ||
1118 | while ((ret = git_index_iterator_next(&entry, iterator)) == 0) | |
1119 | ; | |
1120 | ||
1121 | if (ret != GIT_ITEROVER) | |
1122 | cl_git_fail(ret); | |
1123 | ||
1124 | cl_assert_equal_i(found, ARRAY_SIZE(test_entries)); | |
1125 | ||
1126 | git_index_iterator_free(iterator); | |
1127 | git_index_free(index); | |
1128 | } | |
1129 | ||
1130 | void test_index_tests__can_modify_while_iterating(void) | |
1131 | { | |
1132 | git_index *index; | |
1133 | git_index_iterator *iterator; | |
1134 | const git_index_entry *entry; | |
1135 | git_index_entry new_entry = {{0}}; | |
1136 | size_t expected = 0, seen = 0; | |
1137 | int ret; | |
1138 | ||
1139 | cl_git_pass(git_index_open(&index, TEST_INDEX_PATH)); | |
1140 | cl_git_pass(git_index_iterator_new(&iterator, index)); | |
1141 | ||
1142 | expected = git_index_entrycount(index); | |
1143 | cl_assert(git_vector_is_sorted(&iterator->snap)); | |
1144 | ||
1145 | /* | |
1146 | * After we've counted the entries, add a new one and change another; | |
1147 | * ensure that our iterator is backed by a snapshot and thus returns | |
1148 | * the number of entries from when the iterator was created. | |
1149 | */ | |
1150 | cl_git_pass(git_oid_fromstr(&new_entry.id, "8312e0a89a9cbab77c732b6bc39b51a783e3a318")); | |
1151 | new_entry.path = "newfile"; | |
1152 | new_entry.mode = GIT_FILEMODE_BLOB; | |
1153 | cl_git_pass(git_index_add(index, &new_entry)); | |
1154 | ||
1155 | cl_git_pass(git_oid_fromstr(&new_entry.id, "4141414141414141414141414141414141414141")); | |
1156 | new_entry.path = "Makefile"; | |
1157 | new_entry.mode = GIT_FILEMODE_BLOB; | |
1158 | cl_git_pass(git_index_add(index, &new_entry)); | |
1159 | ||
1160 | while (true) { | |
1161 | ret = git_index_iterator_next(&entry, iterator); | |
1162 | ||
1163 | if (ret == GIT_ITEROVER) | |
1164 | break; | |
1165 | ||
1166 | seen++; | |
1167 | } | |
1168 | ||
1169 | cl_assert_equal_i(expected, seen); | |
1170 | ||
1171 | git_index_iterator_free(iterator); | |
1172 | git_index_free(index); | |
1173 | } |