]> git.proxmox.com Git - libgit2.git/blame - tests/submodule/lookup.c
New upstream version 1.1.0+dfsg.1
[libgit2.git] / tests / submodule / lookup.c
CommitLineData
aa13bf05
RB
1#include "clar_libgit2.h"
2#include "submodule_helpers.h"
1e9dd60f 3#include "git2/sys/repository.h"
a34c4f8d 4#include "repository.h"
22a2d3d5 5#include "futils.h"
aa13bf05
RB
6
7static git_repository *g_repo = NULL;
8
9void test_submodule_lookup__initialize(void)
10{
14997dc5 11 g_repo = setup_fixture_submod2();
aa13bf05
RB
12}
13
eae0bfdc
PP
14void test_submodule_lookup__cleanup(void)
15{
16 cl_git_sandbox_cleanup();
17}
18
aa13bf05
RB
19void test_submodule_lookup__simple_lookup(void)
20{
a15c7802 21 assert_submodule_exists(g_repo, "sm_unchanged");
aa13bf05
RB
22
23 /* lookup pending change in .gitmodules that is not in HEAD */
a15c7802 24 assert_submodule_exists(g_repo, "sm_added_and_uncommited");
aa13bf05 25
a15c7802
RB
26 /* lookup pending change in .gitmodules that is not in HEAD nor index */
27 assert_submodule_exists(g_repo, "sm_gitmodules_only");
fed886d9 28
aa13bf05 29 /* lookup git repo subdir that is not added as submodule */
a15c7802 30 refute_submodule_exists(g_repo, "not-submodule", GIT_EEXISTS);
aa13bf05
RB
31
32 /* lookup existing directory that is not a submodule */
a15c7802 33 refute_submodule_exists(g_repo, "just_a_dir", GIT_ENOTFOUND);
aa13bf05
RB
34
35 /* lookup existing file that is not a submodule */
a15c7802 36 refute_submodule_exists(g_repo, "just_a_file", GIT_ENOTFOUND);
aa13bf05
RB
37
38 /* lookup non-existent item */
a15c7802 39 refute_submodule_exists(g_repo, "no_such_file", GIT_ENOTFOUND);
c28a5c97
CMN
40
41 /* lookup a submodule by path with a trailing slash */
42 assert_submodule_exists(g_repo, "sm_added_and_uncommited/");
aa13bf05
RB
43}
44
45void test_submodule_lookup__accessors(void)
46{
47 git_submodule *sm;
48 const char *oid = "480095882d281ed676fe5b863569520e54a7d5c0";
49
50 cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged"));
51 cl_assert(git_submodule_owner(sm) == g_repo);
52 cl_assert_equal_s("sm_unchanged", git_submodule_name(sm));
53 cl_assert(git__suffixcmp(git_submodule_path(sm), "sm_unchanged") == 0);
54 cl_assert(git__suffixcmp(git_submodule_url(sm), "/submod2_target") == 0);
55
9cd42358
RB
56 cl_assert(git_oid_streq(git_submodule_index_id(sm), oid) == 0);
57 cl_assert(git_oid_streq(git_submodule_head_id(sm), oid) == 0);
58 cl_assert(git_oid_streq(git_submodule_wd_id(sm), oid) == 0);
aa13bf05
RB
59
60 cl_assert(git_submodule_ignore(sm) == GIT_SUBMODULE_IGNORE_NONE);
9d1f97df 61 cl_assert(git_submodule_update_strategy(sm) == GIT_SUBMODULE_UPDATE_CHECKOUT);
aa13bf05 62
a15c7802
RB
63 git_submodule_free(sm);
64
65
aa13bf05
RB
66 cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head"));
67 cl_assert_equal_s("sm_changed_head", git_submodule_name(sm));
68
9cd42358
RB
69 cl_assert(git_oid_streq(git_submodule_index_id(sm), oid) == 0);
70 cl_assert(git_oid_streq(git_submodule_head_id(sm), oid) == 0);
71 cl_assert(git_oid_streq(git_submodule_wd_id(sm),
aa13bf05
RB
72 "3d9386c507f6b093471a3e324085657a3c2b4247") == 0);
73
a15c7802
RB
74 git_submodule_free(sm);
75
76
aa13bf05
RB
77 cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited"));
78 cl_assert_equal_s("sm_added_and_uncommited", git_submodule_name(sm));
79
9cd42358
RB
80 cl_assert(git_oid_streq(git_submodule_index_id(sm), oid) == 0);
81 cl_assert(git_submodule_head_id(sm) == NULL);
82 cl_assert(git_oid_streq(git_submodule_wd_id(sm), oid) == 0);
aa13bf05 83
a15c7802
RB
84 git_submodule_free(sm);
85
86
aa13bf05
RB
87 cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_missing_commits"));
88 cl_assert_equal_s("sm_missing_commits", git_submodule_name(sm));
89
9cd42358
RB
90 cl_assert(git_oid_streq(git_submodule_index_id(sm), oid) == 0);
91 cl_assert(git_oid_streq(git_submodule_head_id(sm), oid) == 0);
92 cl_assert(git_oid_streq(git_submodule_wd_id(sm),
aa13bf05 93 "5e4963595a9774b90524d35a807169049de8ccad") == 0);
a15c7802
RB
94
95 git_submodule_free(sm);
aa13bf05
RB
96}
97
98typedef struct {
99 int count;
100} sm_lookup_data;
101
102static int sm_lookup_cb(git_submodule *sm, const char *name, void *payload)
103{
104 sm_lookup_data *data = payload;
105 data->count += 1;
106 cl_assert_equal_s(git_submodule_name(sm), name);
107 return 0;
108}
109
110void test_submodule_lookup__foreach(void)
111{
a34c4f8d 112 git_config *cfg;
aa13bf05 113 sm_lookup_data data;
a34c4f8d
CMN
114
115 memset(&data, 0, sizeof(data));
116 cl_git_pass(git_submodule_foreach(g_repo, sm_lookup_cb, &data));
117 cl_assert_equal_i(8, data.count);
118
aa13bf05 119 memset(&data, 0, sizeof(data));
a34c4f8d
CMN
120
121 /* Change the path for a submodule so it doesn't match the name */
122 cl_git_pass(git_config_open_ondisk(&cfg, "submod2/.gitmodules"));
123
124 cl_git_pass(git_config_set_string(cfg, "submodule.smchangedindex.path", "sm_changed_index"));
125 cl_git_pass(git_config_set_string(cfg, "submodule.smchangedindex.url", "../submod2_target"));
126 cl_git_pass(git_config_delete_entry(cfg, "submodule.sm_changed_index.path"));
127 cl_git_pass(git_config_delete_entry(cfg, "submodule.sm_changed_index.url"));
128
129 git_config_free(cfg);
130
aa13bf05 131 cl_git_pass(git_submodule_foreach(g_repo, sm_lookup_cb, &data));
fed886d9 132 cl_assert_equal_i(8, data.count);
aa13bf05 133}
1e9dd60f 134
4b3ec53c
XL
135static int foreach_cb(git_submodule *sm, const char *name, void *payload)
136{
137 GIT_UNUSED(sm);
138 GIT_UNUSED(name);
139 GIT_UNUSED(payload);
140 return 0;
141}
142
143void test_submodule_lookup__duplicated_path(void)
144{
145 cl_git_rewritefile("submod2/.gitmodules",
146 "[submodule \"sm1\"]\n"
147 " path = duplicated-path\n"
148 " url = sm1\n"
149 "[submodule \"sm2\"]\n"
150 " path = duplicated-path\n"
151 " url = sm2\n");
152
153 cl_git_fail(git_submodule_foreach(g_repo, foreach_cb, NULL));
154}
155
605da51a 156void test_submodule_lookup__lookup_even_with_unborn_head(void)
1e9dd60f 157{
605da51a 158 git_reference *head;
1e9dd60f 159
605da51a 160 /* put us on an unborn branch */
1e9dd60f 161 cl_git_pass(git_reference_symbolic_create(
659cf202 162 &head, g_repo, "HEAD", "refs/heads/garbage", 1, NULL));
605da51a 163 git_reference_free(head);
1e9dd60f 164
8061d519 165 test_submodule_lookup__simple_lookup(); /* baseline should still pass */
1e9dd60f
RB
166}
167
168void test_submodule_lookup__lookup_even_with_missing_index(void)
169{
170 git_index *idx;
1e9dd60f
RB
171
172 /* give the repo an empty index */
173 cl_git_pass(git_index_new(&idx));
174 git_repository_set_index(g_repo, idx);
175 git_index_free(idx);
176
8061d519 177 test_submodule_lookup__simple_lookup(); /* baseline should still pass */
1e9dd60f 178}
380f864a 179
aa51fa1e
CMN
180void test_submodule_lookup__backslashes(void)
181{
182 git_config *cfg;
183 git_submodule *sm;
184 git_repository *subrepo;
185 git_buf buf = GIT_BUF_INIT;
186 const char *backslashed_path = "..\\submod2_target";
187
188 cl_git_pass(git_config_open_ondisk(&cfg, "submod2/.gitmodules"));
189 cl_git_pass(git_config_set_string(cfg, "submodule.sm_unchanged.url", backslashed_path));
190 git_config_free(cfg);
191
192 cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged"));
193 cl_assert_equal_s(backslashed_path, git_submodule_url(sm));
194 cl_git_pass(git_submodule_open(&subrepo, sm));
195
196 cl_git_pass(git_submodule_resolve_url(&buf, g_repo, backslashed_path));
197
ac3d33df 198 git_buf_dispose(&buf);
aa51fa1e
CMN
199 git_submodule_free(sm);
200 git_repository_free(subrepo);
201}
202
8f4e5275
RB
203static void baseline_tests(void)
204{
205 /* small baseline that should work even if we change the index or make
206 * commits from the index
207 */
208 assert_submodule_exists(g_repo, "sm_unchanged");
209 assert_submodule_exists(g_repo, "sm_gitmodules_only");
210 refute_submodule_exists(g_repo, "not-submodule", GIT_EEXISTS);
211}
212
213static void add_submodule_with_commit(const char *name)
214{
215 git_submodule *sm;
216 git_repository *smrepo;
217 git_index *idx;
218 git_buf p = GIT_BUF_INIT;
219
220 cl_git_pass(git_submodule_add_setup(&sm, g_repo,
221 "https://github.com/libgit2/libgit2.git", name, 1));
222
223 assert_submodule_exists(g_repo, name);
224
225 cl_git_pass(git_submodule_open(&smrepo, sm));
226 cl_git_pass(git_repository_index(&idx, smrepo));
227
228 cl_git_pass(git_buf_joinpath(&p, git_repository_workdir(smrepo), "file"));
229 cl_git_mkfile(p.ptr, "new file");
ac3d33df 230 git_buf_dispose(&p);
8f4e5275
RB
231
232 cl_git_pass(git_index_add_bypath(idx, "file"));
233 cl_git_pass(git_index_write(idx));
234 git_index_free(idx);
235
236 cl_repo_commit_from_index(NULL, smrepo, NULL, 0, "initial commit");
237 git_repository_free(smrepo);
238
239 cl_git_pass(git_submodule_add_finalize(sm));
240
241 git_submodule_free(sm);
242}
243
380f864a
RB
244void test_submodule_lookup__just_added(void)
245{
246 git_submodule *sm;
8061d519 247 git_buf snap1 = GIT_BUF_INIT, snap2 = GIT_BUF_INIT;
8f4e5275 248 git_reference *original_head = NULL;
8061d519
RB
249
250 refute_submodule_exists(g_repo, "sm_just_added", GIT_ENOTFOUND);
251 refute_submodule_exists(g_repo, "sm_just_added_2", GIT_ENOTFOUND);
8f4e5275
RB
252 refute_submodule_exists(g_repo, "sm_just_added_idx", GIT_ENOTFOUND);
253 refute_submodule_exists(g_repo, "sm_just_added_head", GIT_ENOTFOUND);
8061d519
RB
254 refute_submodule_exists(g_repo, "mismatch_name", GIT_ENOTFOUND);
255 refute_submodule_exists(g_repo, "mismatch_path", GIT_ENOTFOUND);
8f4e5275 256 baseline_tests();
380f864a 257
8061d519 258 cl_git_pass(git_futils_readbuffer(&snap1, "submod2/.gitmodules"));
8f4e5275 259 cl_git_pass(git_repository_head(&original_head, g_repo));
8061d519
RB
260
261 cl_git_pass(git_submodule_add_setup(&sm, g_repo,
262 "https://github.com/libgit2/libgit2.git", "sm_just_added", 1));
380f864a
RB
263 git_submodule_free(sm);
264 assert_submodule_exists(g_repo, "sm_just_added");
265
8061d519
RB
266 cl_git_pass(git_submodule_add_setup(&sm, g_repo,
267 "https://github.com/libgit2/libgit2.git", "sm_just_added_2", 1));
380f864a 268 assert_submodule_exists(g_repo, "sm_just_added_2");
8f4e5275 269 cl_git_fail(git_submodule_add_finalize(sm)); /* fails if no HEAD */
380f864a
RB
270 git_submodule_free(sm);
271
8f4e5275
RB
272 add_submodule_with_commit("sm_just_added_head");
273 cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "commit new sm to head");
274 assert_submodule_exists(g_repo, "sm_just_added_head");
275
276 add_submodule_with_commit("sm_just_added_idx");
277 assert_submodule_exists(g_repo, "sm_just_added_idx");
278
8061d519 279 cl_git_pass(git_futils_readbuffer(&snap2, "submod2/.gitmodules"));
380f864a 280
8061d519
RB
281 cl_git_append2file(
282 "submod2/.gitmodules",
283 "\n[submodule \"mismatch_name\"]\n"
284 "\tpath = mismatch_path\n"
285 "\turl = https://example.com/example.git\n\n");
380f864a
RB
286
287 assert_submodule_exists(g_repo, "mismatch_name");
288 assert_submodule_exists(g_repo, "mismatch_path");
8061d519
RB
289 assert_submodule_exists(g_repo, "sm_just_added");
290 assert_submodule_exists(g_repo, "sm_just_added_2");
8f4e5275
RB
291 assert_submodule_exists(g_repo, "sm_just_added_idx");
292 assert_submodule_exists(g_repo, "sm_just_added_head");
293 baseline_tests();
8061d519
RB
294
295 cl_git_rewritefile("submod2/.gitmodules", snap2.ptr);
ac3d33df 296 git_buf_dispose(&snap2);
380f864a 297
8061d519
RB
298 refute_submodule_exists(g_repo, "mismatch_name", GIT_ENOTFOUND);
299 refute_submodule_exists(g_repo, "mismatch_path", GIT_ENOTFOUND);
380f864a
RB
300 assert_submodule_exists(g_repo, "sm_just_added");
301 assert_submodule_exists(g_repo, "sm_just_added_2");
8f4e5275
RB
302 assert_submodule_exists(g_repo, "sm_just_added_idx");
303 assert_submodule_exists(g_repo, "sm_just_added_head");
304 baseline_tests();
380f864a 305
8061d519 306 cl_git_rewritefile("submod2/.gitmodules", snap1.ptr);
ac3d33df 307 git_buf_dispose(&snap1);
380f864a 308
8061d519
RB
309 refute_submodule_exists(g_repo, "mismatch_name", GIT_ENOTFOUND);
310 refute_submodule_exists(g_repo, "mismatch_path", GIT_ENOTFOUND);
311 /* note error code change, because add_setup made a repo in the workdir */
312 refute_submodule_exists(g_repo, "sm_just_added", GIT_EEXISTS);
313 refute_submodule_exists(g_repo, "sm_just_added_2", GIT_EEXISTS);
8f4e5275
RB
314 /* these still exist in index and head respectively */
315 assert_submodule_exists(g_repo, "sm_just_added_idx");
316 assert_submodule_exists(g_repo, "sm_just_added_head");
317 baseline_tests();
318
319 {
320 git_index *idx;
321 cl_git_pass(git_repository_index(&idx, g_repo));
322 cl_git_pass(git_index_remove_bypath(idx, "sm_just_added_idx"));
323 cl_git_pass(git_index_remove_bypath(idx, "sm_just_added_head"));
324 cl_git_pass(git_index_write(idx));
325 git_index_free(idx);
326 }
327
328 refute_submodule_exists(g_repo, "sm_just_added_idx", GIT_EEXISTS);
329 assert_submodule_exists(g_repo, "sm_just_added_head");
330
331 {
659cf202 332 cl_git_pass(git_reference_create(NULL, g_repo, "refs/heads/master", git_reference_target(original_head), 1, "move head back"));
8f4e5275
RB
333 git_reference_free(original_head);
334 }
335
336 refute_submodule_exists(g_repo, "sm_just_added_head", GIT_EEXISTS);
380f864a 337}
8f4e5275 338
e8e848a8
CMN
339/* Test_App and Test_App2 are fairly similar names, make sure we load the right one */
340void test_submodule_lookup__prefix_name(void)
341{
342 git_submodule *sm;
343
344 cl_git_rewritefile("submod2/.gitmodules",
345 "[submodule \"Test_App\"]\n"
346 " path = Test_App\n"
347 " url = ../Test_App\n"
348 "[submodule \"Test_App2\"]\n"
349 " path = Test_App2\n"
350 " url = ../Test_App\n");
351
352 cl_git_pass(git_submodule_lookup(&sm, g_repo, "Test_App"));
353 cl_assert_equal_s("Test_App", git_submodule_name(sm));
354
355 git_submodule_free(sm);
356
357 cl_git_pass(git_submodule_lookup(&sm, g_repo, "Test_App2"));
358 cl_assert_equal_s("Test_App2", git_submodule_name(sm));
359
360 git_submodule_free(sm);
361}
a3b9731f
CMN
362
363void test_submodule_lookup__renamed(void)
364{
365 const char *newpath = "sm_actually_changed";
366 git_index *idx;
367 sm_lookup_data data;
368
369 cl_git_pass(git_repository_index__weakptr(&idx, g_repo));
370
371 /* We're replicating 'git mv sm_unchanged sm_actually_changed' in this test */
372
373 cl_git_pass(p_rename("submod2/sm_unchanged", "submod2/sm_actually_changed"));
374
375 /* Change the path in .gitmodules and stage it*/
376 {
377 git_config *cfg;
378
379 cl_git_pass(git_config_open_ondisk(&cfg, "submod2/.gitmodules"));
380 cl_git_pass(git_config_set_string(cfg, "submodule.sm_unchanged.path", newpath));
381 git_config_free(cfg);
382
383 cl_git_pass(git_index_add_bypath(idx, ".gitmodules"));
384 }
385
91f0d186 386 /* Change the worktree info in the submodule's config */
a3b9731f
CMN
387 {
388 git_config *cfg;
389
390 cl_git_pass(git_config_open_ondisk(&cfg, "submod2/.git/modules/sm_unchanged/config"));
391 cl_git_pass(git_config_set_string(cfg, "core.worktree", "../../../sm_actually_changed"));
392 git_config_free(cfg);
393 }
394
395 /* Rename the entry in the index */
396 {
397 const git_index_entry *e;
dfe2856d 398 git_index_entry entry = {{ 0 }};
a3b9731f
CMN
399
400 e = git_index_get_bypath(idx, "sm_unchanged", 0);
401 cl_assert(e);
402 cl_assert_equal_i(GIT_FILEMODE_COMMIT, e->mode);
403
404 entry.path = newpath;
405 entry.mode = GIT_FILEMODE_COMMIT;
406 git_oid_cpy(&entry.id, &e->id);
407
408 cl_git_pass(git_index_remove(idx, "sm_unchanged", 0));
409 cl_git_pass(git_index_add(idx, &entry));
410 cl_git_pass(git_index_write(idx));
411 }
412
413 memset(&data, 0, sizeof(data));
414 cl_git_pass(git_submodule_foreach(g_repo, sm_lookup_cb, &data));
415 cl_assert_equal_i(8, data.count);
416}
4d99c4cf 417
eae0bfdc
PP
418void test_submodule_lookup__cached(void)
419{
4d99c4cf
BP
420 git_submodule *sm;
421 git_submodule *sm2;
422 /* See that the simple tests still pass. */
423
424 git_repository_submodule_cache_all(g_repo);
425 test_submodule_lookup__simple_lookup();
426 git_repository_submodule_cache_clear(g_repo);
427 test_submodule_lookup__simple_lookup();
428
429 /* Check that subsequent calls return different objects when cached. */
430 git_repository_submodule_cache_all(g_repo);
431 cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged"));
432 cl_git_pass(git_submodule_lookup(&sm2, g_repo, "sm_unchanged"));
433 cl_assert_equal_p(sm, sm2);
434 git_submodule_free(sm2);
435
436 /* and that we get new objects again after clearing the cache. */
437 git_repository_submodule_cache_clear(g_repo);
438 cl_git_pass(git_submodule_lookup(&sm2, g_repo, "sm_unchanged"));
439 cl_assert(sm != sm2);
440 git_submodule_free(sm);
441 git_submodule_free(sm2);
442}
eae0bfdc
PP
443
444void test_submodule_lookup__lookup_in_bare_repository_fails(void)
445{
446 git_submodule *sm;
447
448 cl_git_sandbox_cleanup();
449 g_repo = cl_git_sandbox_init("submodules.git");
450
451 cl_git_fail(git_submodule_lookup(&sm, g_repo, "nonexisting"));
452}
453
eae0bfdc
PP
454void test_submodule_lookup__foreach_in_bare_repository_fails(void)
455{
456 cl_git_sandbox_cleanup();
457 g_repo = cl_git_sandbox_init("submodules.git");
458
459 cl_git_fail(git_submodule_foreach(g_repo, foreach_cb, NULL));
460}
4b3ec53c
XL
461
462void test_submodule_lookup__fail_invalid_gitmodules(void)
463{
464 git_submodule *sm;
465 sm_lookup_data data;
466 memset(&data, 0, sizeof(data));
467
468 cl_git_rewritefile("submod2/.gitmodules",
469 "[submodule \"Test_App\"\n"
470 " path = Test_App\n"
471 " url = ../Test_App\n");
472
473 cl_git_fail(git_submodule_lookup(&sm, g_repo, "Test_App"));
474
475 cl_git_fail(git_submodule_foreach(g_repo, sm_lookup_cb, &data));
476}